This commit is contained in:
DavidXanatos 2021-09-11 10:05:43 +02:00
parent 8e32916d2c
commit e47339c360
9 changed files with 213 additions and 117 deletions

View File

@ -9,9 +9,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Added
- added ability to rename groups [#1152](https://github.com/sandboxie-plus/Sandboxie/issues/1152)
- added ability to define a custom order for the sandboxes, you can move using the move context menu, or holding alt + arrow key
- added recovery to list to the recovery window: [#988](https://github.com/sandboxie-plus/Sandboxie/issues/988)
- added finder to the recovery window
### Changed
- updated the BlockPort rule inside Template_BlockPorts to the new NetworkAccess format (by isaak654) [#1162](https://github.com/sandboxie-plus/Sandboxie/pull/1162)
- default for immediate recovery behavioure is now th show the recovery window instzead of using the notifications window [#988](https://github.com/sandboxie-plus/Sandboxie/issues/988)
- the new run dialog now takes double click [#1171](https://github.com/sandboxie-plus/Sandboxie/issues/1171)
- reworked the recovery window
### Fixed
- fixed issue with create group menu [#1151](https://github.com/sandboxie-plus/Sandboxie/issues/1151)

View File

@ -5885,24 +5885,26 @@ _FX NTSTATUS File_SetDisposition(
THREAD_DATA *TlsData = Dll_GetTlsData(&LastError);
UNICODE_STRING uni;
//WCHAR *DosPath;
NTSTATUS status;
ULONG mp_flags;
ULONG FileFlags;
//
// check if the specified path is an open or closed path
//
RtlInitUnicodeString(&uni, L"");
mp_flags = 0;
FileFlags = 0;
//DosPath = NULL;
Dll_PushTlsNameBuffer(TlsData);
__try {
WCHAR *TruePath, *CopyPath;
ULONG FileFlags;
RtlInitUnicodeString(&uni, L"");
status = File_GetName(
FileHandle, &uni, &TruePath, &CopyPath, &FileFlags);
@ -5912,6 +5914,37 @@ _FX NTSTATUS File_SetDisposition(
if (PATH_IS_CLOSED(mp_flags))
status = STATUS_ACCESS_DENIED;
else if (PATH_NOT_OPEN(mp_flags)) {
status = File_DeleteDirectory(CopyPath, TRUE);
if (status != STATUS_DIRECTORY_NOT_EMPTY)
status = STATUS_SUCCESS;
/*
if (NT_SUCCESS(status) && Dll_ChromeSandbox) {
//
// if this is a Chrome sandbox process, we have
// to pass a DOS path to NtDeleteFile rather
// than a file handle
//
ULONG len = wcslen(TruePath);
DosPath = Dll_AllocTemp((len + 8) * sizeof(WCHAR));
wmemcpy(DosPath, TruePath, len + 1);
if (SbieDll_TranslateNtToDosPath(DosPath)) {
len = wcslen(DosPath);
wmemmove(DosPath + 4, DosPath, len + 1);
wmemcpy(DosPath, File_BQQB, 4);
} else {
Dll_Free(DosPath);
DosPath = NULL;
}
}
*/
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
@ -5924,7 +5957,7 @@ _FX NTSTATUS File_SetDisposition(
// handle the request appropriately
//
if (PATH_IS_OPEN(mp_flags) /*|| (FileFlags & FGN_IS_BOXED_PATH) != 0*/) {
if (PATH_IS_OPEN(mp_flags)) {
status = __sys_NtSetInformationFile(
FileHandle, IoStatusBlock,
@ -5932,12 +5965,6 @@ _FX NTSTATUS File_SetDisposition(
} else if (NT_SUCCESS(status)) {
IoStatusBlock->Status = 0;
IoStatusBlock->Information = 8;
}
if (NT_SUCCESS(status) && !PATH_IS_OPEN(mp_flags)) {
BOOLEAN DeleteOnClose = FALSE;
if (FileInformationClass == FileDispositionInformation) {
@ -5965,8 +5992,28 @@ _FX NTSTATUS File_SetDisposition(
on_close->DeleteOnClose = DeleteOnClose;
LeaveCriticalSection(&File_HandleOnClose_CritSec);
/*
OBJECT_ATTRIBUTES objattrs;
InitializeObjectAttributes(
&objattrs, &uni, OBJ_CASE_INSENSITIVE, FileHandle, NULL);
if (DosPath) {
objattrs.RootDirectory = NULL;
RtlInitUnicodeString(&uni, DosPath);
}
status = File_NtDeleteFileImpl(&objattrs);
*/
IoStatusBlock->Status = 0;
IoStatusBlock->Information = 8;
}
//if (DosPath)
// Dll_Free(DosPath);
SetLastError(LastError);
return status;
}

View File

@ -2081,30 +2081,22 @@ _FX NTSTATUS File_NtCloseImpl(HANDLE FileHandle)
status = File_GetName(
FileHandle, &uni, &TruePath, &CopyPath, &FileFlags);
status = File_DeleteDirectory(CopyPath, TRUE);
ULONG len = wcslen(TruePath);
DeletePath = Dll_AllocTemp((len + 8) * sizeof(WCHAR));
wmemcpy(DeletePath, TruePath, len + 1);
if (status != STATUS_DIRECTORY_NOT_EMPTY)
status = STATUS_SUCCESS;
if (Dll_ChromeSandbox) {
if (NT_SUCCESS(status)) {
//
// if this is a Chrome sandbox process, we have
// to pass a DOS path to NtDeleteFile rather
// than a file handle
//
ULONG len = wcslen(TruePath);
DeletePath = Dll_AllocTemp((len + 8) * sizeof(WCHAR));
wmemcpy(DeletePath, TruePath, len + 1);
if (Dll_ChromeSandbox) {
//
// if this is a Chrome sandbox process, we have
// to pass a DOS path to NtDeleteFile rather
// than a file handle
//
if (SbieDll_TranslateNtToDosPath(DeletePath)) {
len = wcslen(DeletePath);
wmemmove(DeletePath + 4, DeletePath, len + 1);
wmemcpy(DeletePath, File_BQQB, 4);
}
if (SbieDll_TranslateNtToDosPath(DeletePath)) {
len = wcslen(DeletePath);
wmemmove(DeletePath + 4, DeletePath, len + 1);
wmemcpy(DeletePath, File_BQQB, 4);
}
}

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>521</width>
<width>512</width>
<height>360</height>
</rect>
</property>
@ -36,36 +36,8 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="1" colspan="4">
<widget class="QComboBox" name="cmbRecover"/>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="btnRefresh">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="5">
<widget class="QLabel" name="lblInfo">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QPushButton" name="btnDeleteAll">
<property name="text">
<string>Delete all</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="btnAddFolder">
<property name="text">
<string>Add Folder</string>
</property>
</widget>
<item row="0" column="0" rowspan="3" colspan="5">
<widget class="QTreeView" name="treeFiles"/>
</item>
<item row="3" column="0">
<widget class="QWidget" name="finder" native="true">
@ -77,14 +49,29 @@
</property>
</widget>
</item>
<item row="5" column="5">
<widget class="QPushButton" name="btnRecover">
<item row="5" column="1" colspan="3">
<widget class="QComboBox" name="cmbRecover"/>
</item>
<item row="6" column="4">
<widget class="QToolButton" name="btnClose">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Recover</string>
<string>Close</string>
</property>
</widget>
</item>
<item row="6" column="3">
<item row="6" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -97,18 +84,25 @@
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label">
<item row="4" column="1" colspan="4">
<widget class="QLabel" name="lblInfo">
<property name="text">
<string>Recover to:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3" colspan="6">
<widget class="QTreeView" name="treeFiles"/>
<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">
@ -117,17 +111,46 @@
</property>
</widget>
</item>
<item row="6" column="5">
<widget class="QPushButton" name="btnClose">
<item row="5" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Close</string>
<string>Recover target:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QCheckBox" name="chkRemember">
<item row="5" column="4">
<widget class="QToolButton" name="btnRecover">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>75</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Remember Target</string>
<string>Recover</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="btnAddFolder">
<property name="text">
<string>Add Folder</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="btnRefresh">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
@ -141,7 +164,6 @@
<tabstop>treeFiles</tabstop>
<tabstop>chkShowAll</tabstop>
<tabstop>btnDeleteAll</tabstop>
<tabstop>btnClose</tabstop>
</tabstops>
<resources/>
<connections/>

View File

@ -1073,24 +1073,25 @@ void CSandMan::OnQueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 Req
void CSandMan::OnFileToRecover(const QString& BoxName, const QString& FilePath, const QString& BoxPath, quint32 ProcessId)
{
CSandBoxPtr pBox = theAPI->GetBoxByName(BoxName);
if (!pBox.isNull() && pBox.objectCast<CSandBoxPlus>()->IsRecoverySuspended())
return;
if (theConf->GetBool("Options/InstantRecovery", true))
{
CSandBoxPtr pBox = theAPI->GetBoxByName(BoxName);
if (pBox) {
CRecoveryWindow* pWnd = ShowRecovery(pBox, false);
CRecoveryWindow* pWnd = ShowRecovery(pBox, false);
if (!theConf->GetBool("Options/AlwaysOnTop", false)) {
SetWindowPos((HWND)pWnd->winId(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
QTimer::singleShot(100, this, [pWnd]() {
SetWindowPos((HWND)pWnd->winId(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
});
}
pWnd->AddFile(FilePath, BoxPath);
if (!theConf->GetBool("Options/AlwaysOnTop", false)) {
SetWindowPos((HWND)pWnd->winId(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
QTimer::singleShot(100, this, [pWnd]() {
SetWindowPos((HWND)pWnd->winId(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
});
}
pWnd->AddFile(FilePath, BoxPath);
}
else
m_pPopUpWindow->AddFileToRecover(FilePath, BoxPath, BoxName, ProcessId);
m_pPopUpWindow->AddFileToRecover(FilePath, BoxPath, pBox, ProcessId);
}
bool CSandMan::OpenRecovery(const CSandBoxPtr& pBox, bool bCloseEmpty)

View File

@ -311,22 +311,18 @@ void CPopUpWindow::SendPromptResult(CPopUpPrompt* pEntry, int retval)
pEntry->m_pProcess.objectCast<CSbieProcess>()->SetRememberedAction(pEntry->m_Result["id"].toInt(), retval);
}
void CPopUpWindow::AddFileToRecover(const QString& FilePath, QString BoxPath, const QString& BoxName, quint32 ProcessId)
void CPopUpWindow::AddFileToRecover(const QString& FilePath, QString BoxPath, const CSandBoxPtr& pBox, quint32 ProcessId)
{
CSandBoxPtr pBox = theAPI->GetBoxByName(BoxName);
if (!pBox.isNull() && pBox.objectCast<CSandBoxPlus>()->IsRecoverySuspended())
return;
CBoxedProcessPtr pProcess = theAPI->GetProcessById(ProcessId);
QString Message = tr("%1 is eligible for quick recovery from %2.\r\nThe file was written by: %3")
.arg(FilePath.mid(FilePath.lastIndexOf("\\") + 1)).arg(QString(BoxName).replace("_", " "))
.arg(FilePath.mid(FilePath.lastIndexOf("\\") + 1)).arg(QString(pBox->GetName()).replace("_", " "))
.arg(pProcess.isNull() ? tr("an UNKNOWN process.") : tr("%1 (%2)").arg(pProcess->GetProcessName()).arg(pProcess->GetProcessId()));
if (BoxPath.isEmpty()) // legacy case, no BoxName, no support for driver serial numbers
BoxPath = theAPI->GetBoxedPath(BoxName, FilePath);
BoxPath = theAPI->GetBoxedPath(pBox->GetName(), FilePath);
CPopUpRecovery* pEntry = new CPopUpRecovery(Message, FilePath, BoxPath, BoxName, this);
CPopUpRecovery* pEntry = new CPopUpRecovery(Message, FilePath, BoxPath, pBox->GetName(), this);
QStringList RecoverTargets = theAPI->GetUserSettings()->GetTextList("SbieCtrl_RecoverTarget", true);
pEntry->m_pTarget->insertItems(pEntry->m_pTarget->count()-1, RecoverTargets);

View File

@ -418,7 +418,7 @@ public:
virtual void AddLogMessage(const QString& Message, quint32 MsgCode, const QStringList& MsgData, quint32 ProcessId);
virtual void AddUserPrompt(quint32 RequestId, const QVariantMap& Data, quint32 ProcessId);
virtual void AddFileToRecover(const QString& FilePath, QString BoxPath, const QString& BoxName, quint32 ProcessId);
virtual void AddFileToRecover(const QString& FilePath, QString BoxPath, const CSandBoxPtr& pBox, quint32 ProcessId);
virtual void ShowProgress(quint32 MsgCode, const QStringList& MsgData, quint32 ProcessId);
static void SetDarkMode(bool bDark) { extern bool CPopUpWindow__DarkMode; CPopUpWindow__DarkMode = bDark; }

View File

@ -92,6 +92,13 @@ CRecoveryWindow::CRecoveryWindow(const CSandBoxPtr& pBox, QWidget *parent)
connect(ui.btnDeleteAll, SIGNAL(clicked(bool)), this, SLOT(OnDeleteAll()));
connect(ui.btnClose, SIGNAL(clicked(bool)), this, SLOT(close()));
QMenu* pRecMenu = new QMenu(ui.btnRecover);
m_pRemember = pRecMenu->addAction(tr("Remember target selection"), this, SLOT(OnCloseUntill()));
m_pRemember->setCheckable(true);
ui.btnRecover->setPopupMode(QToolButton::MenuButtonPopup);
ui.btnRecover->setMenu(pRecMenu);
restoreGeometry(theConf->GetBlob("RecoveryWindow/Window_Geometry"));
QByteArray Columns = theConf->GetBlob("RecoveryWindow/TreeView_Columns");
@ -118,7 +125,7 @@ CRecoveryWindow::CRecoveryWindow(const CSandBoxPtr& pBox, QWidget *parent)
ui.cmbRecover->insertItems(ui.cmbRecover->count()-1, RecoverTargets);
m_LastTargetIndex = theConf->GetInt("RecoveryWindow/LastTarget", -1);
ui.chkRemember->setChecked(m_LastTargetIndex != -1);
m_pRemember->setChecked(m_LastTargetIndex != -1);
if (m_LastTargetIndex == -1)
m_LastTargetIndex = 0;
ui.cmbRecover->setCurrentIndex(m_LastTargetIndex);
@ -198,7 +205,7 @@ void CRecoveryWindow::OnRecover()
theAPI->GetUserSettings()->UpdateTextList("SbieCtrl_RecoverTarget", RecoverTargets, true);
}
theConf->SetValue("RecoveryWindow/LastTarget", ui.chkRemember->isChecked() ? m_LastTargetIndex : -1);
theConf->SetValue("RecoveryWindow/LastTarget", m_pRemember->isChecked() ? m_LastTargetIndex : -1);
QString RecoveryFolder;
if (ui.cmbRecover->currentIndex() > 0)
@ -216,9 +223,15 @@ void CRecoveryWindow::OnDeleteAll()
void CRecoveryWindow::AddFile(const QString& FilePath, const QString& BoxPath)
{
ui.chkShowAll->setTristate(true);
if (m_FileMap.isEmpty())
if (m_FileMap.isEmpty()) {
ui.chkShowAll->setCheckState(Qt::PartiallyChecked);
QMenu* pCloseMenu = new QMenu(ui.btnClose);
pCloseMenu->addAction(tr("Close untill all programs stop in this box"), this, SLOT(OnCloseUntill()));
ui.btnClose->setPopupMode(QToolButton::MenuButtonPopup);
ui.btnClose->setMenu(pCloseMenu);
}
m_NewFiles.insert(FilePath);
if (m_FileMap.isEmpty())
@ -324,6 +337,7 @@ QPair<int, quint64> CRecoveryWindow::FindFiles(const QString& BoxedFolder, const
RecFile["DiskPath"] = RealPath;
RecFile["BoxPath"] = Path;
RecFile["Icon"] = m_IconProvider.icon(Info);
RecFile["IsDir"] = false;
m_FileMap.insert(RealPath, RecFile);
}
else
@ -344,6 +358,7 @@ QPair<int, quint64> CRecoveryWindow::FindFiles(const QString& BoxedFolder, const
RecFolder["DiskPath"] = RealFolder;
RecFolder["BoxPath"] = BoxedFolder;
RecFolder["Icon"] = m_IconProvider.icon(QFileIconProvider::Folder);
RecFolder["IsDir"] = true;
m_FileMap.insert(RealFolder, RecFolder);
}
@ -364,7 +379,7 @@ void CRecoveryWindow::RecoverFiles(bool bBrowse, QString RecoveryFolder)
if (File.isEmpty())
continue;
if (!File["ParentID"].isNull())
if (File["IsDir"].toBool() == false)
{
//if (File["DiskPath"].toString().indexOf("\\device\\mup", 0, Qt::CaseInsensitive) == 0)
// HasShare = true;
@ -372,19 +387,30 @@ void CRecoveryWindow::RecoverFiles(bool bBrowse, QString RecoveryFolder)
}
else
{
for (int i = 0; i < m_pFileModel->rowCount(Index); i++)
QList<QModelIndex> Folders;
Folders.append(ModelIndex);
do
{
QModelIndex ChildIndex = m_pFileModel->index(i, 0, Index);
QModelIndex CurIndex = Folders.takeFirst();
for (int i = 0; i < m_pFileModel->rowCount(CurIndex); i++)
{
QModelIndex ChildIndex = m_pFileModel->index(i, 0, CurIndex);
QVariant ChildID = m_pFileModel->GetItemID(ChildIndex);
QVariantMap File = m_FileMap.value(ChildID);
if (File.isEmpty())
continue;
QVariant ChildID = m_pFileModel->GetItemID(ChildIndex);
QVariantMap File = m_FileMap.value(ChildID);
if (File.isEmpty())
continue;
//if (File["DiskPath"].toString().indexOf("\\device\\mup") == 0)
// HasShare = true;
FileMap[File["BoxPath"].toString()] = File["DiskPath"].toString();
}
if (File["IsDir"].toBool() == false)
{
//if (File["DiskPath"].toString().indexOf("\\device\\mup") == 0)
// HasShare = true;
FileMap[File["BoxPath"].toString()] = File["DiskPath"].toString();
}
else
Folders.append(ChildIndex);
}
} while (!Folders.isEmpty());
}
}
@ -434,6 +460,12 @@ void CRecoveryWindow::OnCount(quint32 fileCount, quint32 folderCount, quint64 to
ui.lblInfo->setText(tr("There are %1 files and %2 folders in the sandbox, occupying %3 of disk space.").arg(fileCount).arg(folderCount).arg(FormatSize(totalSize)));
}
void CRecoveryWindow::OnCloseUntill()
{
m_pBox.objectCast<CSandBoxPlus>()->SetSuspendRecovery();
close();
}
void CRecoveryCounter::run()
{
quint32 fileCount = 0;

View File

@ -56,7 +56,7 @@ private slots:
void OnRecover();
void OnTargetChanged();
void OnDeleteAll();
void OnCloseUntill();
void OnCount(quint32 fileCount, quint32 folderCount, quint64 totalSize);
protected:
@ -83,6 +83,7 @@ protected:
private:
Ui::RecoveryWindow ui;
QAction* m_pRemember;
CSimpleTreeModel* m_pFileModel;
QSortFilterProxyModel* m_pSortProxy;