This commit is contained in:
DavidXanatos 2023-07-30 14:28:35 +02:00
parent c638c63c36
commit 3912dbfd53
20 changed files with 1158 additions and 527 deletions

View File

@ -6,6 +6,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [1.10.2 / 5.65.2] - 2023-07-?? ## [1.10.2 / 5.65.2] - 2023-07-??
### Added
- re-added option to suspend sandboxed processes [#3126](https://github.com/sandboxie-plus/Sandboxie/issues/3126)
### Changed ### Changed
- changed format of the addon data [#3135](https://github.com/sandboxie-plus/Sandboxie/issues/3135) - changed format of the addon data [#3135](https://github.com/sandboxie-plus/Sandboxie/issues/3135)
- all users coming from versions 1.10.0 and 1.10.1 will need to reinstall the components in the addon manager - all users coming from versions 1.10.0 and 1.10.1 will need to reinstall the components in the addon manager

View File

@ -54,7 +54,7 @@ CBoxedProcess::CBoxedProcess(quint32 ProcessId, class CSandBox* pBox)
m_ReturnCode = STATUS_PENDING; m_ReturnCode = STATUS_PENDING;
m_uTerminated = 0; m_uTerminated = 0;
//m_bSuspended = IsSuspended(); m_bSuspended = false;
m_bIsWoW64 = false; m_bIsWoW64 = false;
} }
@ -280,6 +280,8 @@ void CBoxedProcess::InitProcessInfoImpl(void* ProcessHandle)
{ {
m_WorkingDir = CBoxedProcess__GetPebString(ProcessHandle, PhpoCurrentDirectory); m_WorkingDir = CBoxedProcess__GetPebString(ProcessHandle, PhpoCurrentDirectory);
} }
m_bSuspended = IsSuspended();
} }
bool CBoxedProcess::InitProcessInfoEx() bool CBoxedProcess::InitProcessInfoEx()
@ -291,14 +293,20 @@ bool CBoxedProcess::InitProcessInfoEx()
return true; return true;
} }
//extern "C" extern "C"
//{ {
// NTSYSCALLAPI NTSTATUS NTAPI NtTerminateProcess(_In_opt_ HANDLE ProcessHandle, _In_ NTSTATUS ExitStatus); NTSYSCALLAPI NTSTATUS NTAPI NtTerminateProcess(_In_opt_ HANDLE ProcessHandle, _In_ NTSTATUS ExitStatus);
// NTSYSCALLAPI NTSTATUS NTAPI NtSuspendProcess(_In_ HANDLE ProcessHandle); NTSYSCALLAPI NTSTATUS NTAPI NtSuspendProcess(_In_ HANDLE ProcessHandle);
// NTSYSCALLAPI NTSTATUS NTAPI NtResumeProcess(_In_ HANDLE ProcessHandle); NTSYSCALLAPI NTSTATUS NTAPI NtResumeProcess(_In_ HANDLE ProcessHandle);
//}
#include <TlHelp32.h> NTSYSCALLAPI NTSTATUS NTAPI NtGetNextThread(HANDLE ProcessHandle, HANDLE ThreadHandle, ACCESS_MASK DesiredAccess, ULONG HandleAttributes, ULONG Flags, PHANDLE NewThreadHandle);
#define OBJ_KERNEL_EXCLUSIVE 0x00010000L
#define OBJ_VALID_PRIVATE_ATTRIBUTES 0x00010000L
#define OBJ_ALL_VALID_ATTRIBUTES (OBJ_VALID_PRIVATE_ATTRIBUTES | OBJ_VALID_ATTRIBUTES)
}
//#include <TlHelp32.h>
SB_STATUS CBoxedProcess::Terminate() SB_STATUS CBoxedProcess::Terminate()
{ {
@ -327,7 +335,7 @@ bool CBoxedProcess::IsTerminated(quint64 forMs) const
return ::GetTickCount64() - m_uTerminated > forMs; return ::GetTickCount64() - m_uTerminated > forMs;
} }
/*SB_STATUS CBoxedProcess::SetSuspend(bool bSet) SB_STATUS CBoxedProcess::SetSuspend(bool bSet)
{ {
HANDLE ProcessHandle = OpenProcess(PROCESS_SUSPEND_RESUME, FALSE, (DWORD)m_ProcessId); HANDLE ProcessHandle = OpenProcess(PROCESS_SUSPEND_RESUME, FALSE, (DWORD)m_ProcessId);
if (ProcessHandle != INVALID_HANDLE_VALUE) if (ProcessHandle != INVALID_HANDLE_VALUE)
@ -351,43 +359,26 @@ bool CBoxedProcess::IsSuspended() const
{ {
bool isSuspended = true; bool isSuspended = true;
// todo: do that globally once per sec for all boxed processes for(HANDLE hThread = NULL;;)
// Note: If the specified process is a 64-bit process and the caller is a 32-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299).
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap == INVALID_HANDLE_VALUE)
return false;
THREADENTRY32 te32 = { 0 };
te32.dwSize = sizeof(THREADENTRY32);
if (Thread32First(hThreadSnap, &te32))
{ {
do HANDLE nNextThread = NULL;
{ NTSTATUS status = NtGetNextThread(m->Handle, hThread, THREAD_QUERY_INFORMATION, 0, 0, &nNextThread);
if (te32.th32OwnerProcessID != m_ProcessId) if(hThread) NtClose(hThread);
continue; if (!NT_SUCCESS(status))
break;
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID); hThread = nNextThread;
ULONG SuspendCount = 0; ULONG SuspendCount = 0;
NTSTATUS status = NtQueryInformationThread(hThread, (THREADINFOCLASS)35/ThreadSuspendCount/, &SuspendCount, sizeof(ULONG), NULL); status = NtQueryInformationThread(hThread, (THREADINFOCLASS)35/*ThreadSuspendCount*/, &SuspendCount, sizeof(ULONG), NULL);
if (SuspendCount == 0) {
CloseHandle(hThread); isSuspended = false;
NtClose(hThread);
if (SuspendCount == 0) break;
{ }
isSuspended = false; }
break;
}
} while (Thread32Next(hThreadSnap, &te32));
}
CloseHandle(hThreadSnap);
return isSuspended; return isSuspended;
} }
*/
void CBoxedProcess::ResolveSymbols(const QVector<quint64>& Addresses) void CBoxedProcess::ResolveSymbols(const QVector<quint64>& Addresses)
{ {

View File

@ -47,8 +47,8 @@ public:
virtual bool IsTerminated(quint64 forMs = 0) const; virtual bool IsTerminated(quint64 forMs = 0) const;
virtual void SetTerminated(); virtual void SetTerminated();
//virtual SB_STATUS SetSuspend(bool bSet); virtual SB_STATUS SetSuspend(bool bSet);
//virtual bool IsSuspended() const; virtual bool IsSuspended() const;
virtual bool IsWoW64() const { return m_bIsWoW64; } virtual bool IsWoW64() const { return m_bIsWoW64; }
@ -79,7 +79,7 @@ protected:
QDateTime m_StartTime; QDateTime m_StartTime;
quint32 m_ReturnCode; quint32 m_ReturnCode;
quint64 m_uTerminated; quint64 m_uTerminated;
//bool m_bSuspended; bool m_bSuspended;
bool m_bIsWoW64; bool m_bIsWoW64;
class CSandBox* m_pBox; class CSandBox* m_pBox;

View File

@ -9,7 +9,7 @@
#include <QJsonObject> #include <QJsonObject>
#include "../QSbieAPI/Sandboxie/SbieTemplates.h" #include "../QSbieAPI/Sandboxie/SbieTemplates.h"
#include <QtConcurrent> #include <QtConcurrent>
#include "../MiscHelpers/Archive/Archive.h" #include "../../SandboxieTools/UpdUtil/UpdUtil.h"
#include <Windows.h> #include <Windows.h>
@ -27,8 +27,8 @@ void CAddonManager::UpdateAddonsWhenNotCached()
OnUpdateData(Data, QVariantMap()); OnUpdateData(Data, QVariantMap());
return; return;
} }
else if (!m_Addons.isEmpty()) { else if (!m_KnownAddons.isEmpty()) {
QFileInfo info(theConf->GetConfigDir() + "/addons.json"); QFileInfo info(theConf->GetConfigDir() + "/" ADDONS_FILE);
if (info.birthTime() > QDateTime::currentDateTime().addDays(-1)) if (info.birthTime() > QDateTime::currentDateTime().addDays(-1))
return; return;
} }
@ -49,77 +49,111 @@ void CAddonManager::OnUpdateData(const QVariantMap& Data, const QVariantMap& Par
QVariantMap Addons = Data["addons"].toMap(); QVariantMap Addons = Data["addons"].toMap();
QJsonDocument doc(QJsonValue::fromVariant(Addons).toObject()); QJsonDocument doc(QJsonValue::fromVariant(Addons).toObject());
QFile::remove(theConf->GetConfigDir() + "/addons.json"); QFile::remove(theConf->GetConfigDir() + "/" ADDONS_FILE);
WriteStringToFile(theConf->GetConfigDir() + "/addons.json", doc.toJson()); WriteStringToFile(theConf->GetConfigDir() + "/" ADDONS_FILE, doc.toJson());
LoadAddons(); LoadAddons();
emit DataUpdated(); emit DataUpdated();
} }
QList<CAddonPtr> CAddonManager::GetAddons() QList<CAddonInfoPtr> CAddonManager::GetAddons()
{ {
if (m_Addons.isEmpty()) { if (m_KnownAddons.isEmpty()) {
if (!LoadAddons()) if (!LoadAddons())
UpdateAddons(); UpdateAddons();
} }
else {
foreach(const CAddonPtr& pAddon, m_Addons) QMap<QString, CAddonInfoPtr> Addons;
pAddon->Installed = CheckAddon(pAddon);
m_Installed.clear();
QDir Dir(theAPI->GetSbiePath() + ADDONS_PATH);
foreach(const QFileInfo & Info, Dir.entryInfoList(QStringList() << "*.json", QDir::Files | QDir::Hidden | QDir::System)) {
QString AddonPath = theAPI->GetSbiePath() + ADDONS_PATH + Info.fileName();
QString AddonStr = ReadFileAsString(AddonPath);
QVariantMap Data = QJsonDocument::fromJson(AddonStr.toUtf8()).toVariant().toMap();
m_Installed.append(CAddonPtr(new CAddon(Data)));
Addons.insert(Data["id"].toString().toLower(), CAddonInfoPtr(new CAddonInfo(Data, true)));
} }
return m_Addons;
foreach(const CAddonPtr& pAddon, m_KnownAddons) {
CAddonInfoPtr& pInfo = Addons[pAddon->Id.toLower()];
if (pInfo.isNull()) {
bool Installed = false;
QString Key = pAddon->GetSpecificEntry("uninstallKey").toString();
if (!Key.isEmpty()) {
QSettings settings(Key, QSettings::NativeFormat);
QString Uninstall = settings.value("UninstallString").toString();
if (!Uninstall.isEmpty()) {
Installed = true;
m_Installed.append(CAddonPtr(new CAddon(pAddon->Data)));
}
}
pInfo = CAddonInfoPtr(new CAddonInfo(pAddon->Data, Installed));
}
else if (pInfo->Data["version"] != pAddon->Data["version"])
pInfo->UpdateVersion = pAddon->Data["version"].toString();
}
return Addons.values();
} }
bool CAddonManager::LoadAddons() bool CAddonManager::LoadAddons()
{ {
m_Addons.clear(); m_KnownAddons.clear();
QString AddonPath = theConf->GetConfigDir() + "/addons.json"; QString AddonPath = theConf->GetConfigDir() + "/" ADDONS_FILE;
QVariantMap Data = QJsonDocument::fromJson(ReadFileAsString(AddonPath).toUtf8()).toVariant().toMap(); QString AddonStr = ReadFileAsString(AddonPath);
foreach(const QVariant vAddon, Data["list"].toList()) { QVariantMap Data = QJsonDocument::fromJson(AddonStr.toUtf8()).toVariant().toMap();
CAddonPtr pAddon = CAddonPtr(new CAddon(vAddon.toMap())); foreach(const QVariant vAddon, Data["list"].toList())
pAddon->Installed = CheckAddon(pAddon); m_KnownAddons.append(CAddonPtr(new CAddon(vAddon.toMap())));
m_Addons.append(pAddon);
}
return !m_Addons.isEmpty(); return !m_KnownAddons.isEmpty();
} }
CAddonPtr CAddonManager::GetAddon(const QString& Id) CAddonPtr CAddonManager::GetAddon(const QString& Id, EState State)
{ {
if (m_Addons.isEmpty()) if (State != eNotINstalled)
LoadAddons(); {
foreach(const CAddonPtr & pAddon, m_Installed) {
if (pAddon->Id.compare(Id, Qt::CaseInsensitive) == 0)
return pAddon;
}
}
foreach(const CAddonPtr& pAddon, m_Addons) { if (State != eInstalled)
if (pAddon->Id.compare(Id, Qt::CaseInsensitive) == 0) { {
pAddon->Installed = CheckAddon(pAddon); if (m_KnownAddons.isEmpty())
return pAddon; LoadAddons();
foreach(const CAddonPtr & pAddon, m_KnownAddons) {
if (pAddon->Id.compare(Id, Qt::CaseInsensitive) == 0)
return pAddon;
} }
} }
return CAddonPtr(); return CAddonPtr();
} }
bool CAddonManager::HasAddon(const QString& Id) /*bool CAddonManager::CheckAddon(const CAddonPtr& pAddon)
{ {
CAddonPtr pAddon = GetAddon(Id); QString Key = pAddon->GetSpecificEntry("uninstallKey").toString();
return pAddon && pAddon->Installed;
}
bool CAddonManager::CheckAddon(const CAddonPtr& pAddon)
{
QString Key = pAddon->GetSpecificEntry("uninstall_key").toString();
if (!Key.isEmpty()) { if (!Key.isEmpty()) {
QSettings settings(Key, QSettings::NativeFormat); QSettings settings(Key, QSettings::NativeFormat);
QString Uninstall = settings.value("UninstallString").toString(); QString Uninstall = settings.value("UninstallString").toString();
return !Uninstall.isEmpty(); return !Uninstall.isEmpty();
} }
QStringList Files = pAddon->GetSpecificEntry("files").toStringList(); / *QStringList Files = pAddon->GetSpecificEntry("files").toStringList();
foreach(const QString & File, Files) { foreach(const QString & File, Files) {
if (theGUI->GetCompat()->CheckFile(ExpandPath(File))) if (theGUI->GetCompat()->CheckFile(ExpandPath(File)))
return true; return true;
} }
return false; return false;* /
}
QString AddonFile = theAPI->GetSbiePath() + ADDONS_PATH + pAddon->Id + ".json";
return QFile::exists(AddonFile);
}*/
SB_PROGRESS CAddonManager::TryInstallAddon(const QString& Id, QWidget* pParent, const QString& Prompt) SB_PROGRESS CAddonManager::TryInstallAddon(const QString& Id, QWidget* pParent, const QString& Prompt)
{ {
@ -135,151 +169,6 @@ SB_PROGRESS CAddonManager::TryInstallAddon(const QString& Id, QWidget* pParent,
return Status; return Status;
} }
SB_PROGRESS CAddonManager::InstallAddon(const QString& Id)
{
CAddonPtr pAddon = GetAddon(Id);
if (!pAddon)
return SB_ERR(SB_OtherError, QVariantList() << tr("Addon not found, please try updating the addon list in the global settings!"));
if (pAddon->Installed)
return SB_ERR(SB_OtherError, QVariantList() << tr("Addon already installed!"));
QString Entry;
QString Url = pAddon->GetSpecificEntry("download", &Entry).toString();
if (Url.isEmpty())
return SB_ERR(SB_OtherError, QVariantList() << tr("Addon has no download url, addon may not be available for your platform."));
QVariantMap Params;
Params["name"] = Id;
Params["path"] = theGUI->m_pUpdater->GetUpdateDir(true) + "/" + QUrl(Url).fileName();
Params["signature"] = pAddon->Data.value(Entry + "_sig");
theGUI->m_pUpdater->DownloadFile(Url, this, SLOT(OnAddonDownloaded(const QString&, const QVariantMap&)), Params);
pAddon->pProgress = CSbieProgressPtr(new CSbieProgress());
connect(pAddon->pProgress.data(), SIGNAL(Finished()), this, SIGNAL(AddonInstalled()));
pAddon->pProgress->ShowMessage(tr("Downloading Addon %1").arg(pAddon->Id));
return SB_PROGRESS(OP_ASYNC, pAddon->pProgress);
}
extern "C" NTSTATUS VerifyFileSignatureImpl(const wchar_t* FilePath, PVOID Signature, ULONG SignatureSize);
void CAddonManager::OnAddonDownloaded(const QString& Path, const QVariantMap& Params)
{
CAddonPtr pAddon = GetAddon(Params["name"].toString());
QByteArray Signature = QByteArray::fromBase64(Params["signature"].toByteArray());
if (VerifyFileSignatureImpl(QString(Path).replace("/","\\").toStdWString().c_str(), Signature.data(), Signature.size()) < 0) { // !NT_SUCCESS
pAddon->pProgress->Finish(SB_ERR(SB_OtherError, QVariantList() << tr("Download signature is not valid!")));
pAddon->pProgress.create();
return;
}
pAddon->pProgress->ShowMessage(tr("Installing Addon %1").arg(pAddon->Id));
QtConcurrent::run(CAddonManager::InstallAddonAsync, Path, pAddon);
}
void CAddonManager::InstallAddonAsync(const QString& FilePath, CAddonPtr pAddon)
{
SB_STATUS Status = SB_OK;
CArchive Archive(FilePath);
if (Archive.Open() == 1)
{
QString FileDir = Split2(FilePath, ".", true).first.replace("/", "\\");
if (Archive.Extract(FileDir)) {
QString Cmd = pAddon->GetSpecificEntry("installer").toString();
QString Path = ExpandPath(pAddon->GetSpecificEntry("install_path").toString());
if (!Cmd.isEmpty() && QFile::exists(FileDir + Cmd))
{
pAddon->pProgress->ShowMessage(tr("Running Installer for %1").arg(pAddon->Id));
std::wstring sbiehome = theAPI->GetSbiePath().toStdWString();
std::wstring plusdata = theConf->GetConfigDir().toStdWString();
LPWCH environmentStrings = GetEnvironmentStrings();
DWORD environmentLen = 0;
for (LPWCH current = environmentStrings; *current; current += wcslen(current) + 1)
environmentLen += wcslen(current) + 1;
LPWCH modifiedEnvironment = (LPWCH)LocalAlloc(0, (environmentLen + sbiehome.length() + 1 + plusdata.length() + 1 + 1) * sizeof(wchar_t));
memcpy(modifiedEnvironment, environmentStrings, (environmentLen + 1) * sizeof(wchar_t));
FreeEnvironmentStrings(environmentStrings);
LPWCH modifiedEnvironmentEnd = modifiedEnvironment + environmentLen;
wcscpy(modifiedEnvironmentEnd, L"SBIEHOME=");
wcscat(modifiedEnvironmentEnd, sbiehome.c_str());
modifiedEnvironmentEnd += wcslen(modifiedEnvironmentEnd) + 1;
wcscpy(modifiedEnvironmentEnd, L"PLUSDATA=");
wcscat(modifiedEnvironmentEnd, plusdata.c_str());
modifiedEnvironmentEnd += wcslen(modifiedEnvironmentEnd) + 1;
*modifiedEnvironmentEnd = 0;
STARTUPINFO si = { sizeof(si), 0 };
PROCESS_INFORMATION pi = { 0 };
if (CreateProcessW(NULL, (wchar_t*)(FileDir + Cmd).toStdWString().c_str(), NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, modifiedEnvironment, NULL, &si, &pi))
{
while (WaitForSingleObject(pi.hProcess, 1000) == WAIT_TIMEOUT && !pAddon->pProgress->IsCanceled());
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else
Status = SB_ERR(SB_OtherError, QVariantList() << tr("Failed to start installer (%1)!").arg(GetLastError()));
LocalFree(modifiedEnvironment);
}
else if (!Path.isEmpty())
{
pAddon->pProgress->ShowMessage(tr("Copying Files for %1").arg(pAddon->Id));
std::wstring from;
foreach(const QString & file, ListDir(FileDir)) {
QString File = QString(file).replace("/", "\\");
from.append((FileDir + "\\" + File).toStdWString());
from.append(L"\0", 1);
}
from.append(L"\0", 1);
std::wstring to;
to.append(Path.toStdWString());
to.append(L"\0", 1);
SHFILEOPSTRUCT SHFileOp;
memset(&SHFileOp, 0, sizeof(SHFILEOPSTRUCT));
SHFileOp.hwnd = NULL;
SHFileOp.wFunc = FO_MOVE;
SHFileOp.pFrom = from.c_str();
SHFileOp.pTo = to.c_str();
SHFileOp.fFlags = FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
SHFileOperation(&SHFileOp);
}
QDir(FileDir).removeRecursively();
}
else
Status = SB_ERR(SB_OtherError, QVariantList() << tr("Failed to unpack addon!"));
Archive.Close();
}
QFile::remove(FilePath);
if (!Status.IsError()) {
pAddon->Installed = CheckAddon(pAddon);
if (!pAddon->Installed)
Status = SB_ERR(SB_OtherError, QVariantList() << tr("Addon Installation Failed!"));
}
pAddon->pProgress->Finish(Status);
pAddon->pProgress.create();
}
SB_PROGRESS CAddonManager::TryRemoveAddon(const QString& Id, QWidget* pParent) SB_PROGRESS CAddonManager::TryRemoveAddon(const QString& Id, QWidget* pParent)
{ {
if (QMessageBox("Sandboxie-Plus", tr("Do you want to remove %1?").arg(Id), if (QMessageBox("Sandboxie-Plus", tr("Do you want to remove %1?").arg(Id),
@ -294,100 +183,92 @@ SB_PROGRESS CAddonManager::TryRemoveAddon(const QString& Id, QWidget* pParent)
return Status; return Status;
} }
SB_PROGRESS CAddonManager::RemoveAddon(const QString& Id) SB_PROGRESS CAddonManager::InstallAddon(const QString& Id)
{ {
CAddonPtr pAddon = GetAddon(Id); CAddonPtr pAddon = GetAddon(Id, eNotINstalled);
if (!pAddon) if (!pAddon)
return SB_ERR(SB_OtherError, QVariantList() << tr("Addon not found!")); return SB_ERR(SB_OtherError, QVariantList() << tr("Addon not found, please try updating the addon list in the global settings!"));
QFile::remove(theGUI->m_pUpdater->GetUpdateDir(true) + "/" ADDONS_FILE);
QFile::copy(theConf->GetConfigDir() + "/" ADDONS_FILE, theGUI->m_pUpdater->GetUpdateDir(true) + "/" ADDONS_FILE);
QStringList Params;
Params.append("modify");
Params.append("add:" + pAddon->Id);
Params.append("/agent_arch:" + GetAppArch());
Params.append("/framework:" + GetFramework());
Params.append("/step:apply");
Params.append("/embedded");
Params.append("/temp:" + theGUI->m_pUpdater->GetUpdateDir().replace("/", "\\"));
pAddon->pProgress = CSbieProgressPtr(new CSbieProgress()); pAddon->pProgress = CSbieProgressPtr(new CSbieProgress());
QtConcurrent::run(CAddonManager::RemoveAddonAsync, pAddon); QtConcurrent::run(CAddonManager::RunUpdaterAsync, pAddon, Params);
//QTimer::singleShot(10, this, [=]() { CAddonManager::RunUpdaterAsync(pAddon, Params); });
return SB_PROGRESS(OP_ASYNC, pAddon->pProgress); return SB_PROGRESS(OP_ASYNC, pAddon->pProgress);
} }
void CAddonManager::CleanupPath(const QString& Path) SB_PROGRESS CAddonManager::RemoveAddon(const QString& Id)
{ {
StrPair PathName = Split2(Path, "\\", true); CAddonPtr pAddon = GetAddon(Id, eInstalled);
if (ListDir(PathName.first).isEmpty()) if (!pAddon)
return SB_ERR(SB_OtherError, QVariantList() << tr("Addon not found!"));
QStringList Params;
Params.append("modify");
Params.append("remove:" + pAddon->Id);
Params.append("/step:apply");
Params.append("/embedded");
pAddon->pProgress = CSbieProgressPtr(new CSbieProgress());
QtConcurrent::run(CAddonManager::RunUpdaterAsync, pAddon, Params);
//QTimer::singleShot(10, this, [=]() { CAddonManager::RunUpdaterAsync(pAddon, Params); });
return SB_PROGRESS(OP_ASYNC, pAddon->pProgress);
}
QString GetUpdErrorStr(int exitCode);
QString GetUpdErrorStr2(int exitCode)
{
switch (exitCode)
{ {
QDir().rmdir(PathName.first); case ERROR_NO_ADDON: return CAddonManager::tr("Addon Not Found");
//qDebug() << "delete dir" << PathName.first; case ERROR_NO_ADDON2: return CAddonManager::tr("Addon is not available for this paltform");
CleanupPath(PathName.first); case ERROR_BAD_ADDON: return CAddonManager::tr("Missing instalation instructions");
case ERROR_BAD_ADDON2: return CAddonManager::tr("Executing addon setup failed");
case ERROR_DELETE: return CAddonManager::tr("Failed to delete a file during addon removal");
default: return GetUpdErrorStr(exitCode);
} }
} }
void CAddonManager::RemoveAddonAsync(CAddonPtr pAddon) void CAddonManager::RunUpdaterAsync(CAddonPtr pAddon, const QStringList& Params)
{ {
SB_STATUS Status = SB_OK; #ifdef _DEBUG
CSbieResult<int> Status = COnlineUpdater::RunUpdater(Params, false, true);
#else
CSbieResult<int> Status = COnlineUpdater::RunUpdater(Params, true, true);
#endif
QString Key = pAddon->GetSpecificEntry("uninstall_key").toString(); if(Status.IsError())
if (!Key.isEmpty()) pAddon->pProgress->Finish(SB_ERR(SB_OtherError, QVariantList() << tr("Updater failed to to perform plugin operation")));
{ else if(Status.GetValue() < 0)
QSettings settings(Key, QSettings::NativeFormat); pAddon->pProgress->Finish(SB_ERR(SB_OtherError, QVariantList() << tr("Updater failed to to perform plugin operation, error: %1").arg(GetUpdErrorStr2(Status.GetValue()))));
QString Cmd = settings.value("UninstallString").toString();
pAddon->pProgress->ShowMessage(tr("Running Uninstaller for %1").arg(pAddon->Id));
STARTUPINFO si = { sizeof(si), 0 };
PROCESS_INFORMATION pi = { 0 };
if (CreateProcessW(NULL, (wchar_t*)Cmd.toStdWString().c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
while (WaitForSingleObject(pi.hProcess, 1000) == WAIT_TIMEOUT && !pAddon->pProgress->IsCanceled());
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else
Status = SB_ERR(SB_OtherError, QVariantList() << tr("Failed to start uninstaller!"));
}
else else
{ pAddon->pProgress->Finish(SB_OK);
QStringList Files = pAddon->GetSpecificEntry("files").toStringList(); pAddon->pProgress.clear();
//foreach(const QString & File, Files) {
// pAddon->pProgress->ShowMessage(tr("Removing %1").arg(File));
// QString FilePath = ExpandPath(File);
// QFile::remove(FilePath);
// CleanupPath(FilePath);
//}
std::wstring from;
foreach(const QString & File, Files) {
QString FilePath = ExpandPath(File);
if (QFile::exists(FilePath)) {
from.append(FilePath.toStdWString());
from.append(L"\0", 1);
}
}
from.append(L"\0", 1);
SHFILEOPSTRUCT SHFileOp;
memset(&SHFileOp, 0, sizeof(SHFILEOPSTRUCT));
SHFileOp.hwnd = NULL;
SHFileOp.wFunc = FO_DELETE;
SHFileOp.pFrom = from.c_str();
SHFileOp.pTo = NULL;
SHFileOp.fFlags = FOF_NOCONFIRMATION;
SHFileOperation(&SHFileOp);
}
if (!Status.IsError()) {
pAddon->Installed = CheckAddon(pAddon);
if (pAddon->Installed)
Status = SB_ERR(SB_OtherError, QVariantList() << tr("Addon Removal Failed!"));
}
pAddon->pProgress->Finish(Status);
pAddon->pProgress.create();
} }
QString CAddonManager::ExpandPath(QString Path) QString CAddonManager::GetAppArch()
{ {
Path.replace("%SbieHome%", theAPI->GetSbiePath(), Qt::CaseInsensitive); #ifdef _M_ARM64
Path.replace("%PlusData%", theConf->GetConfigDir(), Qt::CaseInsensitive); return "a64";
#elif _WIN64
return theGUI->GetCompat()->ExpandPath(Path); return "x64";
#else
return "x86";
#endif
} }
QString GetArch() QString CAddonManager::GetSysArch()
{ {
SYSTEM_INFO systemInfo; SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo); GetSystemInfo(&systemInfo);
@ -397,42 +278,43 @@ QString GetArch()
case PROCESSOR_ARCHITECTURE_AMD64: return "x64"; case PROCESSOR_ARCHITECTURE_AMD64: return "x64";
case PROCESSOR_ARCHITECTURE_ARM64: return "a64"; case PROCESSOR_ARCHITECTURE_ARM64: return "a64";
} }
return "???"; return GetAppArch(); // fallback
}
QString CAddonManager::GetFramework()
{
QString qt = QString("qt%1.%2.%3").arg(QT_VERSION_MAJOR).arg(QT_VERSION_MINOR).arg(QT_VERSION_PATCH);
#ifdef _DEBUG
qt.append("d");
#endif // _DEBUG
qt.append("_" + GetAppArch());
return qt;
} }
QVariant CAddon::GetSpecificEntry(const QString& Name, QString* pName) QVariant CAddon::GetSpecificEntry(const QString& Name, QString* pName)
{ {
#ifdef _M_ARM64
QString arch = "a64";
#elif _WIN64
QString arch = "x64";
#else
QString arch = "x86";
#endif
// //
// First we check the qt cpecific entry for our version of qt and platform // First we check the qt cpecific entry for our version of qt and platform
// //
QString qt = QString("qt%1_%2_%3_%4").arg(QT_VERSION_MAJOR).arg(QT_VERSION_MINOR).arg(QT_VERSION_PATCH).arg(arch); QString qt = CAddonManager::GetFramework();
#ifdef _DEBUG #ifdef _DEBUG
qt.append("d"); qt.append("d");
#endif // _DEBUG #endif // _DEBUG
if (Data.contains(Name + "_" + qt)) { if (Data.contains(Name + "-" + qt)) {
if (pName) *pName = Name + "_" + qt; if (pName) *pName = Name + "-" + qt;
return Data[Name + "_" + qt]; return Data[Name + "-" + qt];
} }
// //
// Second we check the actual architecture // Second we check the actual architecture
// //
QString match = Data["match_arch"].toString(); QString match = Data["matchArch"].toString();
if (match != "agent") QString arch = match != "agent" ? CAddonManager::GetSysArch() : CAddonManager::GetAppArch();
arch = GetArch(); if (Data.contains(Name + "-" + arch)) {
if (Data.contains(Name + "_" + arch)) { if (pName) *pName = Name + "-" + arch;
if (pName) *pName = Name + "_" + arch; return Data[Name + "-" + arch];
return Data[Name + "_" + arch];
} }
// //
@ -447,7 +329,7 @@ QVariant CAddon::GetSpecificEntry(const QString& Name, QString* pName)
return QString(); return QString();
} }
QString CAddon::GetLocalizedEntry(const QString& Name) QString CAddonInfo::GetLocalizedEntry(const QString& Name)
{ {
if (Data.contains(Name + "_" + theGUI->m_Language)) if (Data.contains(Name + "_" + theGUI->m_Language))
return Data[Name + "_" + theGUI->m_Language].toString(); return Data[Name + "_" + theGUI->m_Language].toString();
@ -458,4 +340,4 @@ QString CAddon::GetLocalizedEntry(const QString& Name)
return Data[Name + "_" + LangAux].toString(); return Data[Name + "_" + LangAux].toString();
return Data[Name].toString(); return Data[Name].toString();
} }

View File

@ -6,21 +6,37 @@
class CAddon : public QObject class CAddon : public QObject
{ {
public: public:
CAddon(const QVariantMap& Data) : Installed(false), Data(Data) CAddon(const QVariantMap& Data) : Data(Data)
{ {
Id = Data["id"].toString(); Id = Data["id"].toString();
} }
QString Id; QString Id;
QVariantMap Data; QVariantMap Data;
bool Installed;
CSbieProgressPtr pProgress; CSbieProgressPtr pProgress;
QVariant GetSpecificEntry(const QString& Name, QString* pName = NULL); QVariant GetSpecificEntry(const QString& Name, QString* pName = NULL);
QString GetLocalizedEntry(const QString& Name);
}; };
typedef QSharedPointer<CAddon> CAddonPtr; typedef QSharedPointer<CAddon> CAddonPtr;
class CAddonInfo
{
public:
CAddonInfo(const QVariantMap& data, bool installed) : Data(data), Installed(installed) {
Id = Data["id"].toString();
};
QString Id;
QVariantMap Data;
bool Installed;
QString UpdateVersion;
QString GetLocalizedEntry(const QString& Name);
};
typedef QSharedPointer<CAddonInfo> CAddonInfoPtr;
class CAddonManager : public QObject class CAddonManager : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -32,15 +48,24 @@ public:
void UpdateAddonsWhenNotCached(); void UpdateAddonsWhenNotCached();
void UpdateAddons(); void UpdateAddons();
QList<CAddonPtr> GetAddons(); QList<CAddonInfoPtr> GetAddons();
CAddonPtr GetAddon(const QString& Id); enum EState {
bool HasAddon(const QString& Id); eAny = 0,
eInstalled,
eNotINstalled
};
CAddonPtr GetAddon(const QString& Id, EState State = eAny);
SB_PROGRESS TryInstallAddon(const QString& Id, QWidget* pParent, const QString& Prompt = QString()); SB_PROGRESS TryInstallAddon(const QString& Id, QWidget* pParent, const QString& Prompt = QString());
SB_PROGRESS InstallAddon(const QString& Id); SB_PROGRESS InstallAddon(const QString& Id);
SB_PROGRESS TryRemoveAddon(const QString& Id, QWidget* pParent); SB_PROGRESS TryRemoveAddon(const QString& Id, QWidget* pParent);
SB_PROGRESS RemoveAddon(const QString& Id); SB_PROGRESS RemoveAddon(const QString& Id);
static QString GetAppArch();
static QString GetSysArch();
static QString GetFramework();
signals: signals:
void DataUpdated(); void DataUpdated();
@ -48,18 +73,12 @@ signals:
private slots: private slots:
void OnUpdateData(const QVariantMap& Data, const QVariantMap& Params); void OnUpdateData(const QVariantMap& Data, const QVariantMap& Params);
void OnAddonDownloaded(const QString& Path, const QVariantMap& Params);
protected: protected:
static bool CheckAddon(const CAddonPtr& pAddon);
static void CleanupPath(const QString& Path); static void RunUpdaterAsync(CAddonPtr pAddon, const QStringList& Params);
static void InstallAddonAsync(const QString& FilePath, CAddonPtr pAddon); QList<CAddonPtr> m_Installed;
static void RemoveAddonAsync(CAddonPtr pAddon); QList<CAddonPtr> m_KnownAddons;
static QString ExpandPath(QString Path);
QList<CAddonPtr> m_Addons;
}; };

View File

@ -1227,6 +1227,11 @@
<string>Status</string> <string>Status</string>
</property> </property>
</column> </column>
<column>
<property name="text">
<string>Version</string>
</property>
</column>
<column> <column>
<property name="text"> <property name="text">
<string>Description</string> <string>Description</string>

View File

@ -676,7 +676,8 @@ bool COnlineUpdater::ApplyUpdate(bool bSilent)
if (Scope == eFull) if (Scope == eFull)
Params.append("/open:sandman.exe"); Params.append("/open:sandman.exe");
if (RunUpdater(Params, bSilent, Scope != eFull)) { SB_RESULT(int) status = RunUpdater(Params, bSilent, Scope != eFull);
if (!status.IsError()) {
if(bSilent) if(bSilent)
theConf->DelValue("Updater/UpdateVersion"); theConf->DelValue("Updater/UpdateVersion");
if (Scope == eMeta) if (Scope == eMeta)
@ -690,15 +691,15 @@ bool COnlineUpdater::ApplyUpdate(bool bSilent)
return false; return false;
} }
bool COnlineUpdater::RunUpdater(const QStringList& Params, bool bSilent, bool Wait) SB_RESULT(int) COnlineUpdater::RunUpdater(const QStringList& Params, bool bSilent, bool Wait)
{ {
if (bSilent) { if (bSilent) {
SB_RESULT(int) Result = theAPI->RunUpdateUtility(Params, 2, Wait); SB_RESULT(int) Result = theAPI->RunUpdateUtility(Params, 2, Wait);
if (!Result.IsError()) if (!Result.IsError())
return true; return Result;
// else fallback to ShellExecuteEx // else fallback to ShellExecuteEx
if (theConf->GetBool("Options/UpdateNoFallback", false)) if (theConf->GetBool("Options/UpdateNoFallback", false))
return false; return Result;
} }
std::wstring wFile = QString(QApplication::applicationDirPath() + "/UpdUtil.exe").replace("/", "\\").toStdWString(); std::wstring wFile = QString(QApplication::applicationDirPath() + "/UpdUtil.exe").replace("/", "\\").toStdWString();
@ -708,7 +709,10 @@ bool COnlineUpdater::RunUpdater(const QStringList& Params, bool bSilent, bool Wa
wParams += L"\"" + Param.toStdWString() + L"\""; wParams += L"\"" + Param.toStdWString() + L"\"";
} }
return RunElevated(wFile, wParams, Wait ? INFINITE : 0) == 0; int ExitCode = RunElevated(wFile, wParams, Wait ? INFINITE : 0);
if (ExitCode == STATUS_PENDING && !Wait)
ExitCode = 0;
return CSbieResult<int>(ExitCode);
} }
void COnlineUpdater::DownloadFile(const QString& Url, QObject* receiver, const char* member, const QVariantMap& Params) void COnlineUpdater::DownloadFile(const QString& Url, QObject* receiver, const char* member, const QVariantMap& Params)

View File

@ -92,8 +92,10 @@ protected:
bool AskDownload(const QVariantMap& Update); bool AskDownload(const QVariantMap& Update);
bool RunUpdater(const QStringList& Params, bool bSilent, bool Wait = false); friend class CAddonManager;
bool RunInstaller2(const QString& FilePath, bool bSilent);
static SB_RESULT(int) RunUpdater(const QStringList& Params, bool bSilent, bool Wait = false);
static bool RunInstaller2(const QString& FilePath, bool bSilent);
CNetworkAccessManager* m_RequestManager; CNetworkAccessManager* m_RequestManager;
CSbieProgressPtr m_pUpdateProgress; CSbieProgressPtr m_pUpdateProgress;

View File

@ -76,8 +76,8 @@ QStringList CSandMan::GetFileCheckers(const CSandBoxPtr& pBox)
{ {
QStringList Checkers; QStringList Checkers;
if (theGUI->GetAddonManager()->HasAddon("FileChecker")) if (!theGUI->GetAddonManager()->GetAddon("FileChecker", CAddonManager::eInstalled).isNull())
Checkers.append(pBox->Expand("powershell -exec bypass -nop -File \"%SbieHome%\\bin\\CheckFile.ps1\" -bin")); Checkers.append(pBox->Expand("powershell -exec bypass -nop -File \"%SbieHome%\\addons\\FileChecker\\CheckFile.ps1\" -bin"));
if (!pBox.isNull()) { if (!pBox.isNull()) {
foreach(const QString & Value, pBox->GetTextList("OnFileRecovery", true, false, true)) { foreach(const QString & Value, pBox->GetTextList("OnFileRecovery", true, false, true)) {

View File

@ -272,8 +272,8 @@ void CSbieView::CreateMenu()
m_pMenuMarkLinger->setCheckable(true); m_pMenuMarkLinger->setCheckable(true);
m_pMenuMarkLeader = m_pMenuPreset->addAction(tr("Set Leader Process"), this, SLOT(OnProcessAction())); m_pMenuMarkLeader = m_pMenuPreset->addAction(tr("Set Leader Process"), this, SLOT(OnProcessAction()));
m_pMenuMarkLeader->setCheckable(true); m_pMenuMarkLeader->setCheckable(true);
//m_pMenuSuspend = m_pMenuProcess->addAction(tr("Suspend"), this, SLOT(OnProcessAction())); m_pMenuSuspend = m_pMenuProcess->addAction(tr("Suspend"), this, SLOT(OnProcessAction()));
//m_pMenuResume = m_pMenuProcess->addAction(tr("Resume"), this, SLOT(OnProcessAction())); m_pMenuResume = m_pMenuProcess->addAction(tr("Resume"), this, SLOT(OnProcessAction()));
} }
void CSbieView::CreateOldMenu() void CSbieView::CreateOldMenu()
@ -607,7 +607,7 @@ bool CSbieView::UpdateMenu(bool bAdvanced, const CSandBoxPtr &pBox, int iSandBox
return bBoxBusy == false; return bBoxBusy == false;
} }
void CSbieView::UpdateProcMenu(const CBoxedProcessPtr& pProcess, int iProcessCount) void CSbieView::UpdateProcMenu(const CBoxedProcessPtr& pProcess, int iProcessCount, int iSuspendedCount)
{ {
m_pMenuLinkTo->setEnabled(iProcessCount == 1); m_pMenuLinkTo->setEnabled(iProcessCount == 1);
@ -640,8 +640,8 @@ void CSbieView::UpdateProcMenu(const CBoxedProcessPtr& pProcess, int iProcessCou
m_pMenuMarkLeader->setChecked(pProcess.objectCast<CSbieProcess>()->IsLeaderProgram()); m_pMenuMarkLeader->setChecked(pProcess.objectCast<CSbieProcess>()->IsLeaderProgram());
} }
//m_pMenuSuspend->setEnabled(iProcessCount > iSuspendedCount); m_pMenuSuspend->setEnabled(iProcessCount > iSuspendedCount);
//m_pMenuResume->setEnabled(iSuspendedCount > 0); m_pMenuResume->setEnabled(iSuspendedCount > 0);
} }
bool CSbieView::UpdateMenu() bool CSbieView::UpdateMenu()
@ -655,7 +655,7 @@ bool CSbieView::UpdateMenu()
int iProcessCount = 0; int iProcessCount = 0;
int iSandBoxeCount = 0; int iSandBoxeCount = 0;
int iGroupe = 0; int iGroupe = 0;
//int iSuspendedCount = 0; int iSuspendedCount = 0;
QModelIndexList Rows = m_pSbieTree->selectedRows(); QModelIndexList Rows = m_pSbieTree->selectedRows();
foreach(const QModelIndex& Index, Rows) foreach(const QModelIndex& Index, Rows)
{ {
@ -666,8 +666,8 @@ bool CSbieView::UpdateMenu()
{ {
m_CurProcesses.append(pProcess); m_CurProcesses.append(pProcess);
iProcessCount++; iProcessCount++;
//if (pProcess->IsSuspended()) if (pProcess->IsSuspended())
// iSuspendedCount++; iSuspendedCount++;
} }
else else
{ {
@ -699,7 +699,7 @@ bool CSbieView::UpdateMenu()
m_pDelGroupe->setVisible(iGroupe > 0 && iSandBoxeCount == 0 && iProcessCount == 0); m_pDelGroupe->setVisible(iGroupe > 0 && iSandBoxeCount == 0 && iProcessCount == 0);
if (!pProcess.isNull()) if (!pProcess.isNull())
UpdateProcMenu(pProcess, iProcessCount); UpdateProcMenu(pProcess, iProcessCount, iSuspendedCount);
return UpdateMenu(bAdvanced, pBox, iSandBoxeCount, bBoxBusy); return UpdateMenu(bAdvanced, pBox, iSandBoxeCount, bBoxBusy);
} }
@ -1596,10 +1596,10 @@ void CSbieView::OnProcessAction(QAction* Action, const QList<CBoxedProcessPtr>&
pProcess.objectCast<CSbieProcess>()->SetLingeringProgram(m_pMenuMarkLinger->isChecked()); pProcess.objectCast<CSbieProcess>()->SetLingeringProgram(m_pMenuMarkLinger->isChecked());
else if (Action == m_pMenuMarkLeader) else if (Action == m_pMenuMarkLeader)
pProcess.objectCast<CSbieProcess>()->SetLeaderProgram(m_pMenuMarkLeader->isChecked()); pProcess.objectCast<CSbieProcess>()->SetLeaderProgram(m_pMenuMarkLeader->isChecked());
/*else if (Action == m_pMenuSuspend) else if (Action == m_pMenuSuspend)
Results.append(pProcess->SetSuspend(true)); Results.append(pProcess->SetSuspend(true));
else if (Action == m_pMenuResume) else if (Action == m_pMenuResume)
Results.append(pProcess->SetSuspend(false));*/ Results.append(pProcess->SetSuspend(false));
} }
theGUI->CheckResults(Results, this); theGUI->CheckResults(Results, this);

View File

@ -124,7 +124,7 @@ private:
void CreateTrayMenu(); void CreateTrayMenu();
bool UpdateMenu(bool bAdvanced, const CSandBoxPtr &pBox, int iSandBoxeCount = 1, bool bBoxBusy = false); bool UpdateMenu(bool bAdvanced, const CSandBoxPtr &pBox, int iSandBoxeCount = 1, bool bBoxBusy = false);
void UpdateProcMenu(const CBoxedProcessPtr &pProcess = CBoxedProcessPtr(), int iProcessCount = 0); void UpdateProcMenu(const CBoxedProcessPtr &pProcess = CBoxedProcessPtr(), int iProcessCount = 0, int iSuspendedCount = 0);
bool UpdateMenu(); bool UpdateMenu();
void UpdateMoveMenu(); void UpdateMoveMenu();
void RenameGroup(const QString OldName, const QString NewName); void RenameGroup(const QString OldName, const QString NewName);
@ -212,8 +212,8 @@ private:
QAction* m_pMenuMarkLinger; QAction* m_pMenuMarkLinger;
QAction* m_pMenuMarkLeader; QAction* m_pMenuMarkLeader;
QAction* m_pMenuPinToRun; QAction* m_pMenuPinToRun;
//QAction* m_pMenuSuspend; QAction* m_pMenuSuspend;
//QAction* m_pMenuResume; QAction* m_pMenuResume;
QAction* m_pRemove; QAction* m_pRemove;

View File

@ -378,7 +378,7 @@ void CTraceView::SetEnabled(bool bSet)
void CTraceView::OnShowStack() void CTraceView::OnShowStack()
{ {
if (!theGUI->GetAddonManager()->HasAddon("DbgHelp")) if (!theGUI->GetAddonManager()->GetAddon("DbgHelp", CAddonManager::eInstalled).isNull())
theGUI->GetAddonManager()->TryInstallAddon("DbgHelp", this, tr("To use the stack traces feature the DbgHelp.dll and SymSrv.dll are required, do you want to download and install them?")); theGUI->GetAddonManager()->TryInstallAddon("DbgHelp", this, tr("To use the stack traces feature the DbgHelp.dll and SymSrv.dll are required, do you want to download and install them?"));
theAPI->GetGlobalSettings()->SetBool("MonitorStackTrace", m_pShowStack->isChecked()); theAPI->GetGlobalSettings()->SetBool("MonitorStackTrace", m_pShowStack->isChecked());
m_pTrace->m_pStackView->setVisible(m_pShowStack->isChecked()); m_pTrace->m_pStackView->setVisible(m_pShowStack->isChecked());

View File

@ -1536,15 +1536,21 @@ void CSettingsWindow::OnOptChanged()
void CSettingsWindow::OnLoadAddon() void CSettingsWindow::OnLoadAddon()
{ {
ui.treeAddons->clear(); ui.treeAddons->clear();
foreach(const CAddonPtr pAddon, theGUI->GetAddonManager()->GetAddons()) { foreach(const CAddonInfoPtr pAddon, theGUI->GetAddonManager()->GetAddons()) {
QTreeWidgetItem* pItem = new QTreeWidgetItem; QTreeWidgetItem* pItem = new QTreeWidgetItem;
pItem->setText(0, pAddon->GetLocalizedEntry("name")); pItem->setText(0, pAddon->GetLocalizedEntry("name"));
if(!pAddon->Data["mandatory"].toBool()) if(!pAddon->Data["mandatory"].toBool())
pItem->setData(0, Qt::UserRole, pAddon->Id); pItem->setData(0, Qt::UserRole, pAddon->Id);
pItem->setIcon(0, pAddon->Data.contains("icon") ? CSandMan::GetIcon(pAddon->Data["icon"].toString()) : CSandMan::GetIcon("Addon")); pItem->setIcon(0, pAddon->Data.contains("icon") ? CSandMan::GetIcon(pAddon->Data["icon"].toString()) : CSandMan::GetIcon("Addon"));
pItem->setText(1, pAddon->Installed ? tr("Installed") : ""); if (pAddon->Installed) {
pItem->setText(2, pAddon->GetLocalizedEntry("description")); if(!pAddon->UpdateVersion.isEmpty())
pItem->setText(1, tr("Update Available"));
else
pItem->setText(1, tr("Installed"));
}
pItem->setText(2, pAddon->Data["version"].toString());
pItem->setText(3, pAddon->GetLocalizedEntry("description"));
ui.treeAddons->addTopLevelItem(pItem); ui.treeAddons->addTopLevelItem(pItem);
} }

View File

@ -96,7 +96,7 @@ void CBoxAssistant::OnToggleDebugger()
{ {
m_bUseDebugger = !m_bUseDebugger; m_bUseDebugger = !m_bUseDebugger;
if (m_bUseDebugger && !theGUI->GetAddonManager()->HasAddon("V4dbg")) if (m_bUseDebugger && theGUI->GetAddonManager()->GetAddon("V4dbg", CAddonManager::eInstalled).isNull())
theGUI->GetAddonManager()->TryInstallAddon("V4dbg", this, tr("To debug troubleshooting scripts you need the V4 Script Debugger addon, do you want to download and install it?")); theGUI->GetAddonManager()->TryInstallAddon("V4dbg", this, tr("To debug troubleshooting scripts you need the V4 Script Debugger addon, do you want to download and install it?"));
QString title = windowTitle(); QString title = windowTitle();

View File

@ -2,8 +2,8 @@
#define VERSION_MJR 1 #define VERSION_MJR 1
#define VERSION_MIN 10 #define VERSION_MIN 10
#define VERSION_REV 1 #define VERSION_REV 2
#define VERSION_UPD 1 #define VERSION_UPD 0
#ifndef STR #ifndef STR
#define STR2(X) #X #define STR2(X) #X

View File

@ -876,7 +876,7 @@ std::wstring JSONValue::StringifyString(const std::wstring &str)
{ {
wchar_t chr = *iter; wchar_t chr = *iter;
if (chr == L'"' || chr == L'\\' || chr == L'/') if (chr == L'"' || chr == L'\\' /*|| chr == L'/'*/)
{ {
str_out += L'\\'; str_out += L'\\';
str_out += chr; str_out += chr;

View File

@ -279,7 +279,6 @@ NTSTATUS MyHashBuffer(
) )
{ {
NTSTATUS status; NTSTATUS status;
IO_STATUS_BLOCK iosb;
MY_HASH_OBJ hashObj; MY_HASH_OBJ hashObj;
if (!NT_SUCCESS(status = MyInitHash(&hashObj))) if (!NT_SUCCESS(status = MyInitHash(&hashObj)))

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,8 @@
#define UPDATE_DOMAIN "sandboxie-plus.com" #define UPDATE_DOMAIN "sandboxie-plus.com"
#define UPDATE_FILE "update.json" #define UPDATE_FILE "update.json"
#define ADDONS_FILE "addons.json"
#define ADDONS_PATH "\\addons\\"
#define SCOPE_CORE_FILES L"32\\SbieDll.dll\0"\ #define SCOPE_CORE_FILES L"32\\SbieDll.dll\0"\
@ -33,5 +35,10 @@
#define ERROR_EXEC (-8) #define ERROR_EXEC (-8)
#define ERROR_CANCELED (-9) #define ERROR_CANCELED (-9)
#define ERROR_INTERNAL (-10) // internal error, should not happen #define ERROR_INTERNAL (-10) // internal error, should not happen
#define ERROR_NO_ADDON (-11) // addon not found
#define ERROR_NO_ADDON2 (-12) // no addon for this paltform or framework
#define ERROR_BAD_ADDON (-13)
#define ERROR_BAD_ADDON2 (-14)
#define ERROR_DELETE (-15)

View File

@ -126,11 +126,12 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies);Version.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -147,7 +148,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies);Version.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -156,11 +157,12 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>noenv.obj;ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>noenv.obj;ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies);Version.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
@ -169,11 +171,12 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>noenv.obj;ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>noenv.obj;ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies);Version.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -190,7 +193,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>noenv.obj;ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>noenv.obj;ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies);Version.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
@ -207,7 +210,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>noenv.obj;ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>noenv.obj;ntdll.lib;bcrypt.lib;wininet.lib;winhttp.lib;%(AdditionalDependencies);Version.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>