This commit is contained in:
DavidXanatos 2022-01-30 15:53:37 +01:00
parent 45152ce01d
commit d34731c1ab
17 changed files with 309 additions and 107 deletions

View File

@ -3,16 +3,19 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [1.0.9 / 5.55.9] - 2022-01-??
## [1.0.9 / 5.55.9] - 2022-01-31
### Added
- sandman now causes all boxed processes to update thair path settings in real time when access options were modified
- added new maintenance meu option Uninstal All to quickly remove all components when runnign in portable mode
- added option to return not to a snapshot but to an empty box state while keeping all snapshots
- Sandboxie-Plus.ini can now be placed in C:\ProgramData\Sandboxie-Plus\ folder and takes precedence (for business use)
### Changed
- reworked breakout mechanism to be service based and not alow the parent process to access the broken out child process
- enabled creatin of directory junctions for sandboxed processes [#1375](https://github.com/sandboxie-plus/Sandboxie/issues/1375)
- changed back to set AutoRecover=y on box creation [#1554](https://github.com/sandboxie-plus/Sandboxie/discussions/1554)
- improved snapshot support [#1220](https://github.com/sandboxie-plus/Sandboxie/issues/1220)
### Fixed
- fixed BreakoutProcess not working with EnableObjectFiltering=y
@ -23,6 +26,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- fixed border issues on maximized windows introduced in the last build [#1561](https://github.com/sandboxie-plus/Sandboxie/issues/1561)
- fixed a couple if index overruns (thanks 7eRoM)
- fixed issues with sysnative directroy [#1403](https://github.com/sandboxie-plus/Sandboxie/issues/1403)
- fixed issue with starting sandman when running sandboxed from context menu [#1579](https://github.com/sandboxie-plus/Sandboxie/issues/1579)
- fixed dark mode flash issue with main window creation
- fixed issues with snapshot error handling

View File

@ -12,7 +12,7 @@ bool TestWriteRight(const QString& Path)
return TestFile.remove();
}
CSettings::CSettings(const QString& AppName, QMap<QString, SSetting> DefaultValues, QObject* qObject) : QObject(qObject)
CSettings::CSettings(const QString& AppName, bool bShared, QMap<QString, SSetting> DefaultValues, QObject* qObject) : QObject(qObject)
{
m_ConfigDir = QCoreApplication::applicationDirPath();
if (!(m_bPortable = QFile::exists(m_ConfigDir + "/" + AppName + ".ini")))
@ -20,8 +20,17 @@ CSettings::CSettings(const QString& AppName, QMap<QString, SSetting> DefaultValu
QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
if (dirs.isEmpty())
m_ConfigDir = QDir::homePath() + "/." + AppName;
//
// if shared is set a new ini is created in the shared location
// and if present take precedence over an ini in a user location
// howeever if the only existing ini is in a user location it will be used
//
else if(bShared && dirs.count() > 2 && (
QFile::exists(dirs[1] + "/" + AppName + "/" + AppName + ".ini") ||
!QFile::exists(dirs[0] + "/" + AppName + "/" + AppName + ".ini") ))
m_ConfigDir = dirs[1] + "/" + AppName;
else
m_ConfigDir = dirs.first() + "/" + AppName;
m_ConfigDir = dirs[0] + "/" + AppName;
QDir().mkpath(m_ConfigDir);
}

View File

@ -97,7 +97,7 @@ public:
virtual bool IsBlob() const {return true;}
};
CSettings(const QString& AppName, QMap<QString, SSetting> DefaultValues = QMap<QString, SSetting>(), QObject* qObject = NULL);
CSettings(const QString& AppName, bool bShared = false, QMap<QString, SSetting> DefaultValues = QMap<QString, SSetting>(), QObject* qObject = NULL);
virtual ~CSettings();
bool SetValue(const QString& key, const QVariant& value);

View File

@ -51,7 +51,7 @@ CSandBox::CSandBox(const QString& BoxName, class CSbieAPI* pAPI) : CSbieIni(BoxN
if (cfglvl == 0)
{
SetBool("AutoRecover", false);
SetBool("AutoRecover", true);
SetBool("BlockNetworkFiles", true);
// recovery
@ -235,7 +235,7 @@ SB_STATUS CSandBox::RemoveBox()
return RemoveSection();
}
QList<SBoxSnapshot> CSandBox::GetSnapshots(QString* pCurrent) const
QList<SBoxSnapshot> CSandBox::GetSnapshots(QString* pCurrent, QString* pDefault) const
{
QSettings ini(m_FilePath + "\\Snapshots.ini", QSettings::IniFormat);
@ -259,12 +259,65 @@ QList<SBoxSnapshot> CSandBox::GetSnapshots(QString* pCurrent) const
if(pCurrent)
*pCurrent = ini.value("Current/Snapshot").toString();
if(pDefault)
*pDefault = ini.value("Current/Default").toString();
return Snapshots;
}
void CSandBox::SetDefaultSnapshot(QString Default)
{
QSettings ini(m_FilePath + "\\Snapshots.ini", QSettings::IniFormat);
ini.setValue("Current/Default", Default);
ini.sync();
}
QString CSandBox::GetDefaultSnapshot(QString* pCurrent) const
{
QSettings ini(m_FilePath + "\\Snapshots.ini", QSettings::IniFormat);
if(pCurrent)
*pCurrent = ini.value("Current/Snapshot").toString();
return ini.value("Current/Default").toString();
}
QStringList CSandBox__BoxSubFolders = QStringList() << "drive" << "user" << "share";
struct SBoxDataFile
{
SBoxDataFile(QString name, bool required, bool recursive) : Name(name), Required(required), Recursive(recursive) {}
QString Name;
bool Required; // fail on fail
bool Recursive;
};
QList<SBoxDataFile> CSandBox__BoxDataFiles = QList<SBoxDataFile>()
<< SBoxDataFile("RegHive", true, false)
;
bool CSandBox::IsInitialized() const
{
if (IsEmpty())
return false;
foreach(const QString & BoxSubFolder, CSandBox__BoxSubFolders) {
if (QDir(m_FilePath + "\\" + BoxSubFolder).exists())
return true;
}
foreach(const SBoxDataFile& BoxDataFile, CSandBox__BoxDataFiles) {
if (BoxDataFile.Required && QFile::exists(m_FilePath + "\\" + BoxDataFile.Name))
return true;
}
return false;
}
bool CSandBox::HasSnapshots() const
{
return QFile::exists(m_FilePath + "\\Snapshots.ini");
}
SB_STATUS CSandBox__MoveFolder(const QString& SourcePath, const QString& ParentFolder, const QString& TargetName)
{
SNtObject src_dir(L"\\??\\" + SourcePath.toStdWString());
@ -282,7 +335,7 @@ SB_PROGRESS CSandBox::TakeSnapshot(const QString& Name)
if (m_pAPI->HasProcesses(m_Name))
return SB_ERR(SB_SnapIsRunning, OP_CONFIRM);
if (IsEmpty())
if (!IsInitialized())
return SB_ERR(SB_SnapIsEmpty);
QStringList Snapshots = ini.childGroups();
@ -295,10 +348,18 @@ SB_PROGRESS CSandBox::TakeSnapshot(const QString& Name)
break;
}
if (!QDir().mkdir(m_FilePath + "\\snapshot-" + ID))
if (!QDir().mkpath(m_FilePath + "\\snapshot-" + ID))
return SB_ERR(SB_SnapMkDirFail);
if (!QFile::copy(m_FilePath + "\\RegHive", m_FilePath + "\\snapshot-" + ID + "\\RegHive"))
return SB_ERR(SB_SnapCopyDatFail);
foreach(const SBoxDataFile& BoxDataFile, CSandBox__BoxDataFiles)
{
if (!QFile::copy(m_FilePath + "\\" + BoxDataFile.Name, m_FilePath + "\\snapshot-" + ID + "\\" + BoxDataFile.Name)) {
if (BoxDataFile.Required)
return SB_ERR(SB_SnapCopyDatFail);
}
else if (BoxDataFile.Required) // this one is incremental, hence delete it from the copy root, after it was copied to the snapshot
QFile::remove(m_FilePath + "\\" + BoxDataFile.Name);
}
ini.setValue("Snapshot_" + ID + "/Name", Name);
ini.setValue("Snapshot_" + ID + "/SnapshotDate", QDateTime::currentDateTime().toTime_t());
@ -400,14 +461,18 @@ SB_STATUS CSandBox__MergeFolders(const CSbieProgressPtr& pProgress, const QStrin
SB_STATUS CSandBox__CleanupSnapshot(const QString& Folder)
{
SNtObject ntHiveFile(L"\\??\\" + (Folder + "\\RegHive").toStdWString());
SB_STATUS status = NtDeleteFile(&ntHiveFile.attr);
if (NT_SUCCESS(status)) {
SNtObject ntSnapshotFile(L"\\??\\" + Folder.toStdWString());
status = NtDeleteFile(&ntSnapshotFile.attr);
foreach(const SBoxDataFile& BoxDataFile, CSandBox__BoxDataFiles)
{
SNtObject ntHiveFile(L"\\??\\" + (Folder + "\\" + BoxDataFile.Name).toStdWString());
SB_STATUS status = NtDeleteFile(&ntHiveFile.attr);
if (NT_SUCCESS(status)) {
SNtObject ntSnapshotFile(L"\\??\\" + Folder.toStdWString());
status = NtDeleteFile(&ntSnapshotFile.attr);
}
if(BoxDataFile.Required)
if (!NT_SUCCESS(status))
return SB_ERR(SB_SnapRmDirFail, QVariantList() << Folder, status);
}
if (!NT_SUCCESS(status))
return SB_ERR(SB_SnapRmDirFail, QVariantList() << Folder, status);
return SB_OK;
}
@ -485,16 +550,30 @@ SB_PROGRESS CSandBox::SelectSnapshot(const QString& ID)
{
QSettings ini(m_FilePath + "\\Snapshots.ini", QSettings::IniFormat);
if (!ini.childGroups().contains("Snapshot_" + ID))
if (!ID.isEmpty() && !ini.childGroups().contains("Snapshot_" + ID))
return SB_ERR(SB_SnapNotFound);
if (m_pAPI->HasProcesses(m_Name))
return SB_ERR(SB_SnapIsRunning, OP_CONFIRM);
if (!QFile::remove(m_FilePath + "\\RegHive"))
return SB_ERR(SB_SnapDelDatFail);
if (!QFile::copy(m_FilePath + "\\snapshot-" + ID + "\\RegHive", m_FilePath + "\\RegHive"))
return SB_ERR(SB_SnapCopyDatFail);
foreach(const SBoxDataFile& BoxDataFile, CSandBox__BoxDataFiles)
{
if (!QFile::exists(m_FilePath + "\\" + BoxDataFile.Name))
continue;
if (!QFile::remove(m_FilePath + "\\" + BoxDataFile.Name)) {
if (BoxDataFile.Required)
return SB_ERR(SB_SnapDelDatFail);
}
if (ID.isEmpty() || BoxDataFile.Recursive)
continue; // this one is incremental, don't restore it
if (!QFile::copy(m_FilePath + "\\snapshot-" + ID + "\\" + BoxDataFile.Name, m_FilePath + "\\" + BoxDataFile.Name)) {
if (BoxDataFile.Required)
return SB_ERR(SB_SnapCopyDatFail);
}
}
ini.setValue("Current/Snapshot", ID);
ini.sync();

View File

@ -59,11 +59,15 @@ public:
virtual bool IsEnabled() const { return m_IsEnabled; }
virtual bool IsEmpty() const;
virtual bool IsInitialized() const;
virtual bool HasSnapshots() const;
virtual SB_PROGRESS CleanBox();
virtual SB_STATUS RenameBox(const QString& NewName);
virtual SB_STATUS RemoveBox();
virtual QList<SBoxSnapshot> GetSnapshots(QString* pCurrent = NULL) const;
virtual QList<SBoxSnapshot> GetSnapshots(QString* pCurrent = NULL, QString* pDefault = NULL) const;
virtual void SetDefaultSnapshot(QString Default);
virtual QString GetDefaultSnapshot(QString* pCurrent = NULL) const;
virtual SB_PROGRESS TakeSnapshot(const QString& Name);
virtual SB_PROGRESS RemoveSnapshot(const QString& ID);
virtual SB_PROGRESS SelectSnapshot(const QString& ID);

View File

@ -91,19 +91,6 @@
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QPushButton" name="btnDeleteAll">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Delete all</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="chkShowAll">
<property name="text">
@ -154,6 +141,25 @@
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QToolButton" name="btnDeleteAll">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>75</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Delete Content</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@ -163,7 +169,6 @@
<tabstops>
<tabstop>treeFiles</tabstop>
<tabstop>chkShowAll</tabstop>
<tabstop>btnDeleteAll</tabstop>
</tabstops>
<resources/>
<connections/>

View File

@ -60,12 +60,8 @@
<string>Selected Snapshot Details</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name:</string>
</property>
</widget>
<item row="0" column="1">
<widget class="QLineEdit" name="txtName"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
@ -77,11 +73,25 @@
</property>
</widget>
</item>
<item row="1" column="1" rowspan="2">
<widget class="QPlainTextEdit" name="txtInfo"/>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="txtName"/>
<item row="0" column="2">
<widget class="QCheckBox" name="chkDefault">
<property name="toolTip">
<string>When deleting a snapshots content, it will be returned to this snapshot instead of to none.</string>
</property>
<property name="text">
<string>Default shapsnot</string>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="2" colspan="2">
<widget class="QPlainTextEdit" name="txtInfo"/>
</item>
</layout>
</widget>
@ -98,20 +108,6 @@
<string>Snapshot Actions</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="3" column="0">
<widget class="QPushButton" name="btnRemove">
<property name="text">
<string>Remove Snapshot</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="btnSelect">
<property name="text">
<string>Go to Snapshot</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="btnTake">
<property name="text">
@ -132,6 +128,32 @@
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="btnRemove">
<property name="text">
<string>Remove Snapshot</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QToolButton" name="btnSelect">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Go to Snapshot</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -147,7 +169,6 @@
<tabstops>
<tabstop>btnTake</tabstop>
<tabstop>treeSnapshots</tabstop>
<tabstop>btnSelect</tabstop>
<tabstop>btnRemove</tabstop>
<tabstop>txtName</tabstop>
<tabstop>txtInfo</tabstop>

View File

@ -116,10 +116,6 @@ CSandMan::CSandMan(QWidget *parent)
QString appTitle = tr("Sandboxie-Plus v%1").arg(GetVersion());
if (QFile::exists(QCoreApplication::applicationDirPath() + "\\Certificate.dat")) {
CSettingsWindow::LoadCertificate();
}
this->setWindowTitle(appTitle);
setAcceptDrops(true);
@ -303,9 +299,6 @@ CSandMan::CSandMan(QWidget *parent)
m_pProgressDialog->setWindowFlag(Qt::WindowStaysOnTopHint, bAlwaysOnTop);
if (!bAutoRun && g_PendingMessage.isEmpty())
show();
//connect(theAPI, SIGNAL(LogMessage(const QString&, bool)), this, SLOT(OnLogMessage(const QString&, bool)));
connect(theAPI, SIGNAL(LogSbieMessage(quint32, const QStringList&, quint32)), this, SLOT(OnLogSbieMessage(quint32, const QStringList&, quint32)));
connect(theAPI, SIGNAL(NotAuthorized(bool, bool&)), this, SLOT(OnNotAuthorized(bool, bool&)), Qt::DirectConnection);
@ -315,6 +308,9 @@ CSandMan::CSandMan(QWidget *parent)
m_uTimerID = startTimer(1000);
if (!bAutoRun && g_PendingMessage.isEmpty())
SafeShow(this);
OnStatusChanged();
if (CSbieUtils::IsRunning(CSbieUtils::eAll) || theConf->GetBool("Options/StartIfStopped", true))
{
@ -899,11 +895,20 @@ void CSandMan::OnBoxClosed(const QString& BoxName)
if (!pBox->GetBool("NeverDelete", false) && pBox->GetBool("AutoDelete", false) && !pBox->IsEmpty())
{
bool DeleteShapshots = false;
// if this box auto deletes first show the recovry dialog with the option to abort deletion
if(!theGUI->OpenRecovery(pBox, true)) // unless no files are found than continue silently
if(!theGUI->OpenRecovery(pBox, DeleteShapshots, true)) // unless no files are found than continue silently
return;
SB_PROGRESS Status = pBox->CleanBox();
SB_PROGRESS Status;
if (!DeleteShapshots && pBox->HasSnapshots()) { // in auto delete mdoe always return to last snapshot
QString Current;
pBox->GetDefaultSnapshot(&Current);
Status = pBox->SelectSnapshot(Current);
}
else // if there are no snapshots jut use the normal cleaning procedure
Status = pBox->CleanBox();
if (Status.GetStatus() == OP_ASYNC)
AddAsyncOp(Status.GetValue());
}
@ -932,9 +937,10 @@ void CSandMan::OnStatusChanged()
if (isConnected)
{
QString SbiePath = theAPI->GetSbiePath();
OnLogMessage(tr("Sbie Directory: %1").arg(SbiePath));
OnLogMessage(tr("Sbie+ Version: %1 (%2)").arg(GetVersion()).arg(theAPI->GetVersion()));
OnLogMessage(tr("Installation Directory: %1").arg(SbiePath));
OnLogMessage(tr("Sandboxie-Plus Version: %1 (%2)").arg(GetVersion()).arg(theAPI->GetVersion()));
OnLogMessage(tr("Loaded Config: %1").arg(theAPI->GetIniPath()));
OnLogMessage(tr("Data Directory: %1").arg(QString(theConf->GetConfigDir()).replace("/","\\")));
//statusBar()->showMessage(tr("Driver version: %1").arg(theAPI->GetVersion()));
@ -1006,6 +1012,10 @@ void CSandMan::OnStatusChanged()
else {
g_Certificate.clear();
g_CertInfo.State = 0;
QString CertPath = QCoreApplication::applicationDirPath() + "\\Certificate.dat";
if(QFile::exists(CertPath)) // always delete invalid certificates
WindowsMoveFile(CertPath.replace("/", "\\"), "");
}
g_FeatureFlags = theAPI->GetFeatureFlags();
@ -1237,7 +1247,7 @@ void CSandMan::OnFileToRecover(const QString& BoxName, const QString& FilePath,
m_pPopUpWindow->AddFileToRecover(FilePath, BoxPath, pBox, ProcessId);
}
bool CSandMan::OpenRecovery(const CSandBoxPtr& pBox, bool bCloseEmpty)
bool CSandMan::OpenRecovery(const CSandBoxPtr& pBox, bool& DeleteShapshots, bool bCloseEmpty)
{
auto pBoxEx = pBox.objectCast<CSandBoxPlus>();
if (pBoxEx->m_pRecoveryWnd != NULL) {
@ -1251,6 +1261,7 @@ bool CSandMan::OpenRecovery(const CSandBoxPtr& pBox, bool bCloseEmpty)
}
else if (pRecoveryWindow->exec() != 1)
return false;
DeleteShapshots = pRecoveryWindow->IsDeleteShapshots();
return true;
}

View File

@ -122,7 +122,7 @@ public slots:
void OnQueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 RequestId, const QVariantMap& Data);
void OnFileToRecover(const QString& BoxName, const QString& FilePath, const QString& BoxPath, quint32 ProcessId);
bool OpenRecovery(const CSandBoxPtr& pBox, bool bCloseEmpty = false);
bool OpenRecovery(const CSandBoxPtr& pBox, bool& DeleteShapshots, bool bCloseEmpty = false);
class CRecoveryWindow* ShowRecovery(const CSandBoxPtr& pBox, bool bFind = true);
void UpdateSettings();

View File

@ -911,6 +911,9 @@ void CSbieView::OnSandBoxAction(QAction* Action)
{
for (QList<QPair<QString, QString>>::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;
@ -957,6 +960,8 @@ void CSbieView::OnSandBoxAction(QAction* Action)
}
else if (Action == m_pMenuCleanUp)
{
bool DeleteShapshots = false;
if (SandBoxes.count() == 1)
{
if (SandBoxes.first()->IsEmpty()) {
@ -967,18 +972,27 @@ void CSbieView::OnSandBoxAction(QAction* Action)
if (theConf->GetBool("Options/ShowRecovery", false))
{
// Use recovery dialog in place of the confirmation messagebox for box clean up
if(!theGUI->OpenRecovery(SandBoxes.first()))
if(!theGUI->OpenRecovery(SandBoxes.first(), DeleteShapshots))
return;
}
else if(QMessageBox("Sandboxie-Plus", tr("Do you want to delete the content of the selected sandbox?"), QMessageBox::Question, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this).exec() != QMessageBox::Yes)
return;
else if(CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("Do you want to delete the content of the selected sandbox?")
, tr("Also delete all Snapshots"), &DeleteShapshots, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes) != QDialogButtonBox::Yes)
return;
}
else if (QMessageBox("Sandboxie-Plus", tr("Do you really want to delete the content of multiple sandboxes?"), QMessageBox::Warning, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this).exec() != QMessageBox::Yes)
return;
else if(CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("Do you really want to delete the content of all sellected sandboxes?")
, tr("Also delete all Snapshots"), &DeleteShapshots, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes) != QDialogButtonBox::Yes)
return;
foreach(const CSandBoxPtr & pBox, SandBoxes)
{
SB_PROGRESS Status = pBox->CleanBox();
SB_PROGRESS Status;
if (!DeleteShapshots && pBox->HasSnapshots()) {
QString Default = pBox->GetDefaultSnapshot();
Status = pBox->SelectSnapshot(Default);
}
else // if there are no snapshots jut use the normal cleaning procedure
Status = pBox->CleanBox();
if (Status.GetStatus() == OP_ASYNC)
theGUI->AddAsyncOp(Status.GetValue());
else if (Status.IsError())
@ -991,7 +1005,7 @@ void CSbieView::OnSandBoxAction(QAction* Action)
{
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, QMessageBox::Information) != QDialogButtonBox::Yes)
, tr("Terminate without asking"), &State, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes) != QDialogButtonBox::Yes)
return;
if (State)
@ -1067,7 +1081,7 @@ void CSbieView::OnProcessAction()
bool State = false;
if(CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("Do you want to %1 %2?").arg(((QAction*)sender())->text().toLower()).arg(Processes.count() == 1 ? Processes[0]->GetProcessName() : tr("the selected processes"))
, tr("Terminate without asking"), &State, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes, QMessageBox::Information) != QDialogButtonBox::Yes)
, tr("Terminate without asking"), &State, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes) != QDialogButtonBox::Yes)
return;
if (State)
@ -1243,21 +1257,6 @@ QList<CBoxedProcessPtr> CSbieView::GetSelectedProcesses()
return List;
}
/*void CSbieView::UpdateRunMenu()
{
while (m_iMenuRun < m_pMenuRun->actions().count())
m_pMenuRun->removeAction(m_pMenuRun->actions().at(m_iMenuRun));
QStringList RunOptions = theConf->ListKeys("RunOptions");
foreach(const QString& RunOption, RunOptions)
{
StrPair NameCmd = Split2(theConf->GetString("RunOptions/" + RunOption), "|");
QAction* pAction = m_pMenuRun->addAction(NameCmd.first, this, SLOT(OnSandBoxAction()));
pAction->setData(NameCmd.second);
}
}*/
void CSbieView::UpdateRunMenu(const CSandBoxPtr& pBox)
{
while (m_iMenuRun < m_pMenuRun->actions().count())

View File

@ -49,6 +49,7 @@ CRecoveryWindow::CRecoveryWindow(const CSandBoxPtr& pBox, QWidget *parent)
m_LastTargetIndex = 0;
m_bTargetsChanged = false;
m_bReloadPending = false;
m_DeleteShapshots = false;
#ifdef WIN32
QStyle* pStyle = QStyleFactory::create("windows");
@ -99,6 +100,10 @@ CRecoveryWindow::CRecoveryWindow(const CSandBoxPtr& pBox, QWidget *parent)
ui.btnRecover->setPopupMode(QToolButton::MenuButtonPopup);
ui.btnRecover->setMenu(pRecMenu);
QMenu* pDelMenu = new QMenu(ui.btnDeleteAll);
pDelMenu->addAction(tr("Delete evertyhign including all snapshots"), this, SLOT(OnDeleteEverything()));
ui.btnDeleteAll->setPopupMode(QToolButton::MenuButtonPopup);
ui.btnDeleteAll->setMenu(pDelMenu);
restoreGeometry(theConf->GetBlob("RecoveryWindow/Window_Geometry"));
@ -145,6 +150,7 @@ int CRecoveryWindow::exec()
{
//QDialog::setWindowModality(Qt::WindowModal);
ui.btnDeleteAll->setVisible(true);
SafeShow(this);
return QDialog::exec();
}
@ -223,6 +229,12 @@ void CRecoveryWindow::OnDeleteAll()
this->close();
}
void CRecoveryWindow::OnDeleteEverything()
{
m_DeleteShapshots = true;
OnDeleteAll();
}
void CRecoveryWindow::AddFile(const QString& FilePath, const QString& BoxPath)
{
ui.chkShowAll->setTristate(true);

View File

@ -39,6 +39,8 @@ public:
CRecoveryWindow(const CSandBoxPtr& pBox, QWidget *parent = Q_NULLPTR);
~CRecoveryWindow();
bool IsDeleteShapshots() { return m_DeleteShapshots; }
virtual void accept() {}
virtual void reject() { this->close(); }
@ -56,6 +58,7 @@ private slots:
void OnRecover();
void OnTargetChanged();
void OnDeleteAll();
void OnDeleteEverything();
void OnCloseUntil();
void OnCount(quint32 fileCount, quint32 folderCount, quint64 totalSize);
@ -80,6 +83,7 @@ protected:
int m_LastTargetIndex;
bool m_bTargetsChanged;
bool m_bReloadPending;
bool m_DeleteShapshots;
private:
Ui::RecoveryWindow ui;

View File

@ -811,7 +811,7 @@ void CSettingsWindow::CertChanged()
void CSettingsWindow::LoadCertificate()
{
QString CertPath;
if (theAPI->IsConnected())
if (theAPI && theAPI->IsConnected())
CertPath = theAPI->GetSbiePath() + "\\Certificate.dat";
else
CertPath = QCoreApplication::applicationDirPath() + "\\Certificate.dat";

View File

@ -96,10 +96,11 @@ union SCertInfo {
quint64 State;
struct {
quint32
valid : 1,
expired : 1,
outdated : 1,
reservd_1 : 5,
valid : 1, // certificate is active
expired : 1, // certificate is expired but may be active
outdated : 1, // certificate is expired, not anymore valid for the current build
business : 1, // certificate is siutable for business use
reservd_1 : 4,
reservd_2 : 8,
reservd_3 : 8,
reservd_4 : 8;

View File

@ -49,11 +49,18 @@ CSnapshotsWindow::CSnapshotsWindow(const CSandBoxPtr& pBox, QWidget *parent)
connect(ui.treeSnapshots->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(UpdateSnapshot(const QModelIndex&)));
connect(ui.treeSnapshots, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(OnSelectSnapshot()));
QMenu* pSelMenu = new QMenu(ui.btnSelect);
pSelMenu->addAction(tr("Revert to empty box"), this, SLOT(OnSelectEmpty()));
ui.btnSelect->setPopupMode(QToolButton::MenuButtonPopup);
ui.btnSelect->setMenu(pSelMenu);
connect(ui.btnTake, SIGNAL(clicked(bool)), this, SLOT(OnTakeSnapshot()));
connect(ui.btnSelect, SIGNAL(clicked(bool)), this, SLOT(OnSelectSnapshot()));
connect(ui.btnRemove, SIGNAL(clicked(bool)), this, SLOT(OnRemoveSnapshot()));
connect(ui.txtName, SIGNAL(textEdited(const QString&)), this, SLOT(SaveInfo()));
connect(ui.chkDefault, SIGNAL(clicked(bool)), this, SLOT(OnChangeDefault()));
connect(ui.txtInfo, SIGNAL(textChanged()), this, SLOT(SaveInfo()));
ui.groupBox->setEnabled(false);
@ -84,13 +91,16 @@ void CSnapshotsWindow::closeEvent(QCloseEvent *e)
void CSnapshotsWindow::UpdateSnapshots(bool AndSelect)
{
m_SnapshotMap.clear();
QList<SBoxSnapshot> SnapshotList = m_pBox->GetSnapshots(&m_CurSnapshot);
QList<SBoxSnapshot> SnapshotList = m_pBox->GetSnapshots(&m_CurSnapshot, &m_DefaultSnapshot);
foreach(const SBoxSnapshot& Snapshot, SnapshotList)
{
QVariantMap BoxSnapshot;
BoxSnapshot["ID"] = Snapshot.ID;
BoxSnapshot["ParentID"] = Snapshot.Parent;
BoxSnapshot["Name"] = Snapshot.NameStr;
if(m_DefaultSnapshot == Snapshot.ID)
BoxSnapshot["Name"] = Snapshot.NameStr + tr(" (default)");
else
BoxSnapshot["Name"] = Snapshot.NameStr;
BoxSnapshot["Info"] = Snapshot.InfoStr;
BoxSnapshot["Date"] = Snapshot.SnapDate;
if(m_CurSnapshot == Snapshot.ID)
@ -131,6 +141,7 @@ void CSnapshotsWindow::UpdateSnapshot(const QModelIndex& Index)
m_SaveInfoPending = -1;
ui.txtName->setText(BoxSnapshot["Name"].toString());
ui.chkDefault->setChecked(ID == m_DefaultSnapshot);
ui.txtInfo->setPlainText(BoxSnapshot["Info"].toString());
m_SaveInfoPending = 0;
@ -173,10 +184,37 @@ void CSnapshotsWindow::OnSelectSnapshot()
//QVariant ID = m_pSnapshotModel->GetItemID(ModelIndex);
QVariant ID = m_pSnapshotModel->GetItemID(Index);
SelectSnapshot(ID.toString());
}
void CSnapshotsWindow::OnSelectEmpty()
{
SelectSnapshot(QString());
}
void CSnapshotsWindow::SelectSnapshot(const QString& ID)
{
if (QMessageBox("Sandboxie-Plus", tr("Do you really want to switch the active snapshot? Doing so will delete the current state!"), QMessageBox::Question, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this).exec() != QMessageBox::Yes)
return;
HandleResult(m_pBox->SelectSnapshot(ID.toString()));
HandleResult(m_pBox->SelectSnapshot(ID));
}
void CSnapshotsWindow::OnChangeDefault()
{
QModelIndex Index = ui.treeSnapshots->currentIndex();
//QModelIndex ModelIndex = m_pSortProxy->mapToSource(Index);
//QVariant ID = m_pSnapshotModel->GetItemID(ModelIndex);
QVariant ID = m_pSnapshotModel->GetItemID(Index);
if (ui.chkDefault->isChecked())
m_DefaultSnapshot = ID.toString();
else
m_DefaultSnapshot.clear();
m_pBox->SetDefaultSnapshot(m_DefaultSnapshot);
UpdateSnapshots();
}
void CSnapshotsWindow::OnRemoveSnapshot()

View File

@ -27,6 +27,8 @@ private slots:
void OnTakeSnapshot();
void OnSelectSnapshot();
void OnSelectEmpty();
void OnChangeDefault();
void OnRemoveSnapshot();
void OnSaveInfo();
@ -34,10 +36,12 @@ private slots:
protected:
void closeEvent(QCloseEvent *e);
void SelectSnapshot(const QString& ID);
void HandleResult(SB_PROGRESS Status);
CSandBoxPtr m_pBox;
QString m_CurSnapshot;
QString m_DefaultSnapshot;
QMap<QVariant, QVariantMap> m_SnapshotMap;
QVariant m_SellectedID;

View File

@ -7,6 +7,7 @@
//#include "../MiscHelpers/Common/qRC4.h"
#include "../MiscHelpers/Common/Common.h"
#include <windows.h>
#include "./Windows/SettingsWindow.h"
CSettings* theConf = NULL;
@ -85,10 +86,18 @@ int main(int argc, char *argv[])
else if (app.sendMessage("ShowWnd"))
return 0;
theConf = new CSettings("Sandboxie-Plus");
if (QFile::exists(QCoreApplication::applicationDirPath() + "\\Certificate.dat")) {
CSettingsWindow::LoadCertificate();
g_CertInfo.business = GetArguments(g_Certificate, L'\n', L':').value("TYPE").toUpper().contains("BUSINESS");
}
// use a shared setting location when used in a business environment for easier administration
theConf = new CSettings("Sandboxie-Plus", g_CertInfo.business);
//QThreadPool::globalInstance()->setMaxThreadCount(theConf->GetInt("Options/MaxThreadPool", 10));
CSandMan* pWnd = new CSandMan();
QObject::connect(&app, SIGNAL(messageReceived(const QString&)), pWnd, SLOT(OnMessage(const QString&)));