Merge branch 'master' into next
This commit is contained in:
commit
51b03496a1
39
CHANGELOG.md
39
CHANGELOG.md
|
@ -18,6 +18,39 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.3 / 5.56.3] - 2022-06-??
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- fixed issue with recovery window on delete [#1948](https://github.com/sandboxie-plus/Sandboxie/issues/1948)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.2 / 5.56.2] - 2022-06-14
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- added missing file recovery log from sbiectrl to sandman [#425](https://github.com/sandboxie-plus/Sandboxie/issues/425)
|
||||||
|
- Immediate recovery window will now auto close when all files are recovered [#1498](https://github.com/sandboxie-plus/Sandboxie/issues/1498)
|
||||||
|
- the Immediate recovery window of sandman is now by default alway on top like in sbiectrl this can be disabled with "Options/RecoveryOnTop=n" [#1465](https://github.com/sandboxie-plus/Sandboxie/issues/1465)
|
||||||
|
- added option to toggle Immediate recovery from the presets sub menu [#1653](https://github.com/sandboxie-plus/Sandboxie/issues/1653)
|
||||||
|
- added option to disable file recovery and or message pop up globally
|
||||||
|
- added per box refresh opzion [#1945](https://github.com/sandboxie-plus/Sandboxie/issues/1945)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- desktop security workaround used for chrome, firefox and acrobat can now be enabled for all processes using "UseSbieDeskHack=y"
|
||||||
|
- inproved double click behavioure [#1935](https://github.com/sandboxie-plus/Sandboxie/issues/1935)
|
||||||
|
- box size info is refreshed on file recovery
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- fixed issue with unnececery sandboxie config reloads introduced in 1.1.1
|
||||||
|
- fixed issue with recovery window focus [#1374](https://github.com/sandboxie-plus/Sandboxie/issues/1374)
|
||||||
|
- fixed issues with desktop objects introduced in 1.1.1 [#1934](https://github.com/sandboxie-plus/Sandboxie/issues/1934)
|
||||||
|
- fixed issues with edge startup boost using a gpo preset
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.1.1 / 5.56.1] - 2022-06-07
|
## [1.1.1 / 5.56.1] - 2022-06-07
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -1025,8 +1058,8 @@ Fixed issue with Windows 7
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- replaced the Process List used by the driver with a much faster Hash Map implementation
|
- replaced the Process List used by the driver with a much faster Hash Map implementation
|
||||||
-- Note: this change provides an almost static system call speed of 1.2µs regardless of the running process count
|
-- Note: this change provides an almost static system call speed of 1.2µs regardless of the running process count
|
||||||
-- The old list, with 100 programs running required 4.5µs; with 200: 12µs; and with 300: 18µs per syscall
|
-- The old list, with 100 programs running required 4.5µs; with 200: 12µs; and with 300: 18µs per syscall
|
||||||
-- Note: some of the slowdown was also affecting non-sandboxed applications due to how the driver handles certain callbacks
|
-- Note: some of the slowdown was also affecting non-sandboxed applications due to how the driver handles certain callbacks
|
||||||
- replaced the per-process Thread List used by the driver with a much faster Hash Map implementation
|
- replaced the per-process Thread List used by the driver with a much faster Hash Map implementation
|
||||||
- replaced configuration section list with a hash map to improve configuration performance, and increased line limit to 100000
|
- replaced configuration section list with a hash map to improve configuration performance, and increased line limit to 100000
|
||||||
|
@ -1653,7 +1686,7 @@ Fixed issue with Windows 7
|
||||||
- added text filter to templates view
|
- added text filter to templates view
|
||||||
- added new compatibility templates:
|
- added new compatibility templates:
|
||||||
-- Windows 10 core UI component: OpenIpcPath=\BaseNamedObjects\[CoreUI]-* solving issues with Chinese Input and Emojis [#120](https://github.com/sandboxie-plus/Sandboxie/issues/120) [#88](https://github.com/sandboxie-plus/Sandboxie/issues/88)
|
-- Windows 10 core UI component: OpenIpcPath=\BaseNamedObjects\[CoreUI]-* solving issues with Chinese Input and Emojis [#120](https://github.com/sandboxie-plus/Sandboxie/issues/120) [#88](https://github.com/sandboxie-plus/Sandboxie/issues/88)
|
||||||
-- Firefox Quantum, access to Windows’ FontCachePort for compatibility with Windows 7
|
-- Firefox Quantum, access to Windows's FontCachePort for compatibility with Windows 7
|
||||||
- added experimental debug option "OriginalToken=y" which lets sandboxed processes retain their original unrestricted token
|
- added experimental debug option "OriginalToken=y" which lets sandboxed processes retain their original unrestricted token
|
||||||
-- This option is comparable with "OpenToken=y" and is intended only for testing and debugging, it BREAKS most SECURITY guarantees (!)
|
-- This option is comparable with "OpenToken=y" and is intended only for testing and debugging, it BREAKS most SECURITY guarantees (!)
|
||||||
- added debug option "NoSandboxieDesktop=y" it disables the desktop proxy mechanism
|
- added debug option "NoSandboxieDesktop=y" it disables the desktop proxy mechanism
|
||||||
|
|
|
@ -112,11 +112,8 @@ typedef BOOL (*P_SaferComputeTokenFromLevel)(
|
||||||
typedef ULONG (*P_GetEffectiveRightsFromAcl)(
|
typedef ULONG (*P_GetEffectiveRightsFromAcl)(
|
||||||
PACL pacl, void *pTrustee, PACCESS_MASK pAccessRights);
|
PACL pacl, void *pTrustee, PACCESS_MASK pAccessRights);
|
||||||
|
|
||||||
//typedef BOOL (*P_EnumWindowStations) (WINSTAENUMPROC lpEnumFunc, LPARAM lParam);
|
typedef BOOL (*P_EnumWindowStations) (_In_ WINSTAENUMPROC lpEnumFunc, _In_ LPARAM lParam);
|
||||||
//typedef HANDLE (*P_OpenWindowStationW) (LPCWSTR lpszWinSta, BOOL fInherit, ACCESS_MASK dwDesiredAccess);
|
typedef HANDLE (*P_OpenWindowStationW) (LPCWSTR lpszWinSta, BOOL fInherit, ACCESS_MASK dwDesiredAccess);
|
||||||
//
|
|
||||||
//typedef BOOL (*P_EnumDesktopsW) (HWINSTA hwinsta, DESKTOPENUMPROCW lpEnumFunc, LPARAM lParam);
|
|
||||||
//typedef HANDLE (*P_OpenDesktopW) (LPCWSTR lpszDesktop, DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess);
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -158,12 +155,8 @@ typedef ULONG (*P_GetEffectiveRightsFromAcl)(
|
||||||
P_SaferComputeTokenFromLevel __sys_SaferComputeTokenFromLevel = NULL;
|
P_SaferComputeTokenFromLevel __sys_SaferComputeTokenFromLevel = NULL;
|
||||||
|
|
||||||
P_GetEffectiveRightsFromAcl __sys_GetEffectiveRightsFromAclW = NULL;
|
P_GetEffectiveRightsFromAcl __sys_GetEffectiveRightsFromAclW = NULL;
|
||||||
|
P_EnumWindowStations __sys_EnumWindowStationsW = NULL;
|
||||||
//P_EnumWindowStations __sys_EnumWindowStationsW = NULL;
|
P_OpenWindowStationW __sys_OpenWindowStationW = NULL;
|
||||||
//P_OpenWindowStationW __sys_OpenWindowStationW = NULL;
|
|
||||||
|
|
||||||
//extern P_EnumDesktopsW __sys_EnumDesktopsW;
|
|
||||||
//extern P_OpenDesktopW __sys_OpenDesktopW;
|
|
||||||
|
|
||||||
|
|
||||||
static HMODULE AdvApi_Module = NULL;
|
static HMODULE AdvApi_Module = NULL;
|
||||||
|
@ -247,7 +240,7 @@ _FX BOOLEAN AdvApi_Init(HMODULE module)
|
||||||
// only hook SetSecurityInfo if this is Chrome. Outlook 2013 uses delayed loading and will cause infinite callbacks
|
// only hook SetSecurityInfo if this is Chrome. Outlook 2013 uses delayed loading and will cause infinite callbacks
|
||||||
// Starting with Win 10, we only want to hook ntmarta!SetSecurityInfo. Do NOT hook advapi!SetSecurityInfo. Delay loading for advapi will cause infinite recursion.
|
// Starting with Win 10, we only want to hook ntmarta!SetSecurityInfo. Do NOT hook advapi!SetSecurityInfo. Delay loading for advapi will cause infinite recursion.
|
||||||
// Note: the infinite recursion issue has been resolved int 5.43
|
// Note: the infinite recursion issue has been resolved int 5.43
|
||||||
if ((Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) || (Dll_ImageType == DLL_IMAGE_ACROBAT_READER)) {
|
if ((Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) || (Dll_ImageType == DLL_IMAGE_MOZILLA_FIREFOX) || (Dll_ImageType == DLL_IMAGE_ACROBAT_READER) || Config_GetSettingsForImageName_bool(L"UseSbieDeskHack", FALSE)) {
|
||||||
SetSecurityInfo = __sys_SetSecurityInfo;
|
SetSecurityInfo = __sys_SetSecurityInfo;
|
||||||
GetSecurityInfo = __sys_GetSecurityInfo;
|
GetSecurityInfo = __sys_GetSecurityInfo;
|
||||||
SBIEDLL_HOOK(AdvApi_, SetSecurityInfo);
|
SBIEDLL_HOOK(AdvApi_, SetSecurityInfo);
|
||||||
|
@ -496,8 +489,12 @@ _FX ULONG AdvApi_CreateRestrictedToken(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*HANDLE Sandboxie_WinSta = 0;
|
|
||||||
HANDLE Sandboxie_Desktop = 0;
|
HANDLE Sandboxie_WinSta = 0;
|
||||||
|
|
||||||
|
BOOL CALLBACK myEnumWindowStationProc(
|
||||||
|
_In_ LPTSTR lpszWindowStation,
|
||||||
|
_In_ LPARAM lParam);
|
||||||
|
|
||||||
// Get Sandbox Dummy WindowStation Handle
|
// Get Sandbox Dummy WindowStation Handle
|
||||||
BOOL CALLBACK myEnumWindowStationProc(
|
BOOL CALLBACK myEnumWindowStationProc(
|
||||||
|
@ -514,37 +511,6 @@ BOOL CALLBACK myEnumWindowStationProc(
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CALLBACK myEnumDesktopsProc(
|
|
||||||
_In_ LPTSTR lpszDesktop,
|
|
||||||
_In_ LPARAM lParam)
|
|
||||||
{
|
|
||||||
if ((!lpszDesktop) || (!__sys_OpenDesktopW)) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (!_wcsnicmp(lpszDesktop, L"Sandbox", 7)) {
|
|
||||||
const ACCESS_MASK DESKTOP_ALL_ACCESS = 0x1FF; // see WinUser.h
|
|
||||||
Sandboxie_Desktop = __sys_OpenDesktopW(lpszDesktop, 0, FALSE, DESKTOP_ALL_ACCESS);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_FX VOID OpenWinSta()
|
|
||||||
{
|
|
||||||
if (!Sandboxie_WinSta) {
|
|
||||||
__sys_EnumWindowStationsW = (P_EnumWindowStations)Ldr_GetProcAddrNew(L"User32.dll", L"EnumWindowStationsW", "EnumWindowStationsW");
|
|
||||||
__sys_OpenWindowStationW = (P_OpenWindowStationW)Ldr_GetProcAddrNew(L"User32.dll", L"OpenWindowStationW", "OpenWindowStationW");
|
|
||||||
if (__sys_EnumWindowStationsW) {
|
|
||||||
__sys_EnumWindowStationsW(myEnumWindowStationProc, 0);
|
|
||||||
|
|
||||||
if (Sandboxie_WinSta) {
|
|
||||||
if (__sys_EnumDesktopsW)
|
|
||||||
__sys_EnumDesktopsW(Sandboxie_WinSta, myEnumDesktopsProc, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// Chrome 52+ now needs to be able to create a WindowStation and Desktop for its sandbox
|
// Chrome 52+ now needs to be able to create a WindowStation and Desktop for its sandbox
|
||||||
// GetSecurityInfo will fail when chrome tries to do a DACL read on the default WindowStation.
|
// GetSecurityInfo will fail when chrome tries to do a DACL read on the default WindowStation.
|
||||||
|
@ -552,8 +518,6 @@ _FX VOID OpenWinSta()
|
||||||
// this will allow chrome to create the required WindowStation and Desktop. See comment in
|
// this will allow chrome to create the required WindowStation and Desktop. See comment in
|
||||||
// GuiServer.cpp: GuiServer::GetWindowStationAndDesktopName.
|
// GuiServer.cpp: GuiServer::GetWindowStationAndDesktopName.
|
||||||
|
|
||||||
extern HANDLE Sandboxie_WinSta;
|
|
||||||
|
|
||||||
_FX DWORD AdvApi_GetSecurityInfo(
|
_FX DWORD AdvApi_GetSecurityInfo(
|
||||||
HANDLE handle,
|
HANDLE handle,
|
||||||
SE_OBJECT_TYPE ObjectType,
|
SE_OBJECT_TYPE ObjectType,
|
||||||
|
@ -568,7 +532,13 @@ _FX DWORD AdvApi_GetSecurityInfo(
|
||||||
rc = __sys_GetSecurityInfo(handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl, ppSecurityDescriptor);
|
rc = __sys_GetSecurityInfo(handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl, ppSecurityDescriptor);
|
||||||
|
|
||||||
if (rc && ObjectType == SE_WINDOW_OBJECT && SecurityInfo == DACL_SECURITY_INFORMATION) {
|
if (rc && ObjectType == SE_WINDOW_OBJECT && SecurityInfo == DACL_SECURITY_INFORMATION) {
|
||||||
//OpenWinSta();
|
__sys_EnumWindowStationsW = (P_EnumWindowStations)Ldr_GetProcAddrNew(L"User32.dll", L"EnumWindowStationsW", "EnumWindowStationsW");
|
||||||
|
__sys_OpenWindowStationW = (P_OpenWindowStationW)Ldr_GetProcAddrNew(L"User32.dll", L"OpenWindowStationW", "OpenWindowStationW");
|
||||||
|
if (!Sandboxie_WinSta) {
|
||||||
|
if (__sys_EnumWindowStationsW) {
|
||||||
|
rc = __sys_EnumWindowStationsW(myEnumWindowStationProc, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
rc = __sys_GetSecurityInfo(Sandboxie_WinSta, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl, ppSecurityDescriptor);
|
rc = __sys_GetSecurityInfo(Sandboxie_WinSta, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl, ppSecurityDescriptor);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -731,7 +701,7 @@ _FX BOOLEAN Ntmarta_Init(HMODULE module)
|
||||||
#define GETPROC2(x,s) __sys_Ntmarta_##x##s = (P_##x) Ldr_GetProcAddrNew(DllName_ntmarta, L#x L#s,#x #s);
|
#define GETPROC2(x,s) __sys_Ntmarta_##x##s = (P_##x) Ldr_GetProcAddrNew(DllName_ntmarta, L#x L#s,#x #s);
|
||||||
|
|
||||||
GETPROC2(GetSecurityInfo, );
|
GETPROC2(GetSecurityInfo, );
|
||||||
if ((Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) || (Dll_ImageType == DLL_IMAGE_ACROBAT_READER)) {
|
if ((Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) || (Dll_ImageType == DLL_IMAGE_MOZILLA_FIREFOX) || (Dll_ImageType == DLL_IMAGE_ACROBAT_READER) || Config_GetSettingsForImageName_bool(L"UseSbieDeskHack", FALSE)) {
|
||||||
|
|
||||||
GetSecurityInfo = __sys_Ntmarta_GetSecurityInfo;
|
GetSecurityInfo = __sys_Ntmarta_GetSecurityInfo;
|
||||||
if (GetSecurityInfo)
|
if (GetSecurityInfo)
|
||||||
|
@ -784,7 +754,13 @@ _FX DWORD Ntmarta_GetSecurityInfo(
|
||||||
rc = __sys_Ntmarta_GetSecurityInfo(handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl, ppSecurityDescriptor);
|
rc = __sys_Ntmarta_GetSecurityInfo(handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl, ppSecurityDescriptor);
|
||||||
|
|
||||||
if (rc && ObjectType == SE_WINDOW_OBJECT && SecurityInfo == DACL_SECURITY_INFORMATION) {
|
if (rc && ObjectType == SE_WINDOW_OBJECT && SecurityInfo == DACL_SECURITY_INFORMATION) {
|
||||||
//OpenWinSta();
|
__sys_EnumWindowStationsW = (P_EnumWindowStations)Ldr_GetProcAddrNew(L"User32.dll", L"EnumWindowStationsW", "EnumWindowStationsW");
|
||||||
|
__sys_OpenWindowStationW = (P_OpenWindowStationW)Ldr_GetProcAddrNew(L"User32.dll", L"OpenWindowStationW", "OpenWindowStationW");
|
||||||
|
if (!Sandboxie_WinSta) {
|
||||||
|
if (__sys_EnumWindowStationsW) {
|
||||||
|
rc = __sys_EnumWindowStationsW(myEnumWindowStationProc, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
rc = __sys_Ntmarta_GetSecurityInfo(Sandboxie_WinSta, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl, ppSecurityDescriptor);
|
rc = __sys_Ntmarta_GetSecurityInfo(Sandboxie_WinSta, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl, ppSecurityDescriptor);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -41,6 +41,7 @@ static BOOLEAN DisableRecycleBin(void);
|
||||||
static BOOLEAN DisableWinRS(void);
|
static BOOLEAN DisableWinRS(void);
|
||||||
static BOOLEAN DisableWerFaultUI(void);
|
static BOOLEAN DisableWerFaultUI(void);
|
||||||
static BOOLEAN EnableMsiDebugging(void);
|
static BOOLEAN EnableMsiDebugging(void);
|
||||||
|
static BOOLEAN DisableEdgeBoost(void);
|
||||||
static BOOLEAN Custom_EnableBrowseNewProcess(void);
|
static BOOLEAN Custom_EnableBrowseNewProcess(void);
|
||||||
static BOOLEAN Custom_DisableBHOs(void);
|
static BOOLEAN Custom_DisableBHOs(void);
|
||||||
static BOOLEAN Custom_OpenWith(void);
|
static BOOLEAN Custom_OpenWith(void);
|
||||||
|
@ -87,6 +88,7 @@ _FX BOOLEAN CustomizeSandbox(void)
|
||||||
DisableWinRS();
|
DisableWinRS();
|
||||||
DisableWerFaultUI();
|
DisableWerFaultUI();
|
||||||
EnableMsiDebugging();
|
EnableMsiDebugging();
|
||||||
|
DisableEdgeBoost();
|
||||||
Custom_EnableBrowseNewProcess();
|
Custom_EnableBrowseNewProcess();
|
||||||
DeleteShellAssocKeys(0);
|
DeleteShellAssocKeys(0);
|
||||||
Custom_DisableBHOs();
|
Custom_DisableBHOs();
|
||||||
|
@ -461,6 +463,44 @@ _FX BOOLEAN EnableMsiDebugging(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// DisableEdgeBoost
|
||||||
|
//
|
||||||
|
// Disable esge startup boost
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
_FX BOOLEAN DisableEdgeBoost(void)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
OBJECT_ATTRIBUTES objattrs;
|
||||||
|
UNICODE_STRING uni;
|
||||||
|
HANDLE hKeyRoot;
|
||||||
|
HANDLE hKeyEdge;
|
||||||
|
|
||||||
|
// Open HKLM
|
||||||
|
RtlInitUnicodeString(&uni, Custom_PrefixHKLM);
|
||||||
|
InitializeObjectAttributes(&objattrs, &uni, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
|
if (NtOpenKey(&hKeyRoot, KEY_READ, &objattrs) == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
// open/create WER parent key
|
||||||
|
RtlInitUnicodeString(&uni, L"SOFTWARE\\Policies\\Microsoft\\Edge");
|
||||||
|
InitializeObjectAttributes(&objattrs, &uni, OBJ_CASE_INSENSITIVE, hKeyRoot, NULL);
|
||||||
|
if (Key_OpenOrCreateIfBoxed(&hKeyEdge, KEY_ALL_ACCESS, &objattrs) == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DWORD StartupBoostEnabled = 0;
|
||||||
|
RtlInitUnicodeString(&uni, L"StartupBoostEnabled");
|
||||||
|
status = NtSetValueKey(hKeyEdge, &uni, 0, REG_DWORD, &StartupBoostEnabled, sizeof(StartupBoostEnabled));
|
||||||
|
|
||||||
|
NtClose(hKeyEdge);
|
||||||
|
}
|
||||||
|
NtClose(hKeyRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Custom_OpenWith
|
// Custom_OpenWith
|
||||||
//
|
//
|
||||||
|
|
|
@ -821,9 +821,6 @@ _FX BOOL DisallowWin32kSystemCallsIsOn()
|
||||||
|
|
||||||
extern P_NtSetInformationThread __sys_NtSetInformationThread;
|
extern P_NtSetInformationThread __sys_NtSetInformationThread;
|
||||||
|
|
||||||
HANDLE Sandboxie_WinSta = NULL;
|
|
||||||
HANDLE Sandboxie_Desktop = NULL;
|
|
||||||
|
|
||||||
_FX BOOLEAN Gui_ConnectToWindowStationAndDesktop(HMODULE User32)
|
_FX BOOLEAN Gui_ConnectToWindowStationAndDesktop(HMODULE User32)
|
||||||
{
|
{
|
||||||
static HDESK _ProcessDesktop = NULL;
|
static HDESK _ProcessDesktop = NULL;
|
||||||
|
@ -903,9 +900,6 @@ _FX BOOLEAN Gui_ConnectToWindowStationAndDesktop(HMODULE User32)
|
||||||
errlvl = 2;
|
errlvl = 2;
|
||||||
else {
|
else {
|
||||||
|
|
||||||
Sandboxie_WinSta = (HANDLE)rpl->hsbie_winsta;
|
|
||||||
Sandboxie_Desktop = (HANDLE)rpl->hsbie_desk;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// locate windowstation and desktop functions in user32 dll
|
// locate windowstation and desktop functions in user32 dll
|
||||||
//
|
//
|
||||||
|
|
|
@ -175,7 +175,6 @@ static BOOLEAN Gui_D3D9_Loaded = FALSE;
|
||||||
|
|
||||||
static ULONG64 Gui_GetShellWindow_LastTicks = 0;
|
static ULONG64 Gui_GetShellWindow_LastTicks = 0;
|
||||||
|
|
||||||
static BOOLEAN Winsta_Hack = FALSE;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Gui_InitEnum
|
// Gui_InitEnum
|
||||||
|
@ -578,18 +577,22 @@ _FX HDESK Gui_OpenDesktopA(
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//Gui_CreateWindowStationW
|
//Gui_CreateWindowStationW
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
extern HANDLE Sandboxie_WinSta;
|
|
||||||
|
|
||||||
_FX HANDLE Gui_CreateWindowStationW (void *lpwinsta, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa) {
|
|
||||||
|
_FX HANDLE Gui_CreateWindowStationW (void *lpwinsta, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa)
|
||||||
|
{
|
||||||
HANDLE myHandle = 0;
|
HANDLE myHandle = 0;
|
||||||
|
|
||||||
myHandle = __sys_CreateWindowStationW(lpwinsta, dwFlags, dwDesiredAccess, lpsa);
|
myHandle = __sys_CreateWindowStationW(lpwinsta, dwFlags, dwDesiredAccess, lpsa);
|
||||||
if (!myHandle) {
|
if (myHandle)
|
||||||
if(Sandboxie_WinSta)
|
return myHandle;
|
||||||
return Sandboxie_WinSta;
|
|
||||||
SbieApi_Log(2205, L"CreateWindowStation");
|
extern HANDLE Sandboxie_WinSta;
|
||||||
}
|
if(Sandboxie_WinSta && ((Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) || (Dll_ImageType == DLL_IMAGE_MOZILLA_FIREFOX) || Config_GetSettingsForImageName_bool(L"UseSbieWndStation", TRUE)))
|
||||||
return myHandle;
|
return Sandboxie_WinSta;
|
||||||
|
|
||||||
|
SbieApi_Log(2205, L"CreateWindowStation");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -598,22 +601,26 @@ _FX HANDLE Gui_CreateWindowStationW (void *lpwinsta, DWORD dwFlags, ACCESS_MASK
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
_FX HANDLE Gui_CreateWindowStationA (void *lpwinsta, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa) {
|
_FX HANDLE Gui_CreateWindowStationA (void *lpwinsta, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa)
|
||||||
|
{
|
||||||
HANDLE myHandle = 0;
|
HANDLE myHandle = 0;
|
||||||
|
|
||||||
myHandle = __sys_CreateWindowStationA(lpwinsta, dwFlags, dwDesiredAccess, lpsa);
|
myHandle = __sys_CreateWindowStationA(lpwinsta, dwFlags, dwDesiredAccess, lpsa);
|
||||||
if (!myHandle) {
|
if (myHandle)
|
||||||
if(Sandboxie_WinSta)
|
return myHandle;
|
||||||
return Sandboxie_WinSta;
|
|
||||||
SbieApi_Log(2205, L"CreateWindowStation");
|
extern HANDLE Sandboxie_WinSta;
|
||||||
}
|
if(Sandboxie_WinSta && ((Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) || (Dll_ImageType == DLL_IMAGE_MOZILLA_FIREFOX) || Config_GetSettingsForImageName_bool(L"UseSbieWndStation", TRUE)))
|
||||||
return myHandle;
|
return Sandboxie_WinSta;
|
||||||
|
|
||||||
|
SbieApi_Log(2205, L"CreateWindowStation");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Gui_CreateDesktopW
|
// Gui_CreateDesktopW
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
extern HANDLE Sandboxie_Desktop;
|
|
||||||
|
|
||||||
_FX HDESK Gui_CreateDesktopW(
|
_FX HDESK Gui_CreateDesktopW(
|
||||||
void *lpszDesktop, void *lpszDevice, void *DevMode, ULONG dwFlags,
|
void *lpszDesktop, void *lpszDevice, void *DevMode, ULONG dwFlags,
|
||||||
|
@ -625,7 +632,7 @@ _FX HDESK Gui_CreateDesktopW(
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (!Config_GetSettingsForImageName_bool(L"UseSbieWndStation", TRUE) && (Dll_ImageType != DLL_IMAGE_GOOGLE_CHROME) && (Dll_ImageType != DLL_IMAGE_MOZILLA_FIREFOX))
|
if ((Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) || (Dll_ImageType == DLL_IMAGE_MOZILLA_FIREFOX) || (Dll_ImageType == DLL_IMAGE_ACROBAT_READER) || Config_GetSettingsForImageName_bool(L"UseSbieDeskHack", FALSE))
|
||||||
{
|
{
|
||||||
//Call the system CreateDesktopW without a security context.
|
//Call the system CreateDesktopW without a security context.
|
||||||
//This works in tandem with the Ntmarta_GetSecurityInfo hook (see in advapi.c).
|
//This works in tandem with the Ntmarta_GetSecurityInfo hook (see in advapi.c).
|
||||||
|
@ -635,12 +642,10 @@ _FX HDESK Gui_CreateDesktopW(
|
||||||
//the sandboxie restricted token by dropping the security context. This won't
|
//the sandboxie restricted token by dropping the security context. This won't
|
||||||
//work without the GetSecurityInfo hook.
|
//work without the GetSecurityInfo hook.
|
||||||
rc = __sys_CreateDesktopW(lpszDesktop, NULL, NULL, dwFlags, dwDesiredAccess, NULL);
|
rc = __sys_CreateDesktopW(lpszDesktop, NULL, NULL, dwFlags, dwDesiredAccess, NULL);
|
||||||
if (rc)
|
//if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Sandboxie_Desktop)
|
|
||||||
return Sandboxie_Desktop;
|
|
||||||
SbieApi_Log(2205, L"CreateDesktop");
|
SbieApi_Log(2205, L"CreateDesktop");
|
||||||
return CreateEvent(NULL, FALSE, FALSE, NULL);
|
return CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
}
|
}
|
||||||
|
@ -661,15 +666,13 @@ _FX HDESK Gui_CreateDesktopA(
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (!Config_GetSettingsForImageName_bool(L"UseSbieWndStation", TRUE) && (Dll_ImageType != DLL_IMAGE_GOOGLE_CHROME) && (Dll_ImageType != DLL_IMAGE_MOZILLA_FIREFOX))
|
if ((Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) || (Dll_ImageType == DLL_IMAGE_MOZILLA_FIREFOX) || (Dll_ImageType == DLL_IMAGE_ACROBAT_READER) || Config_GetSettingsForImageName_bool(L"UseSbieDeskHack", FALSE))
|
||||||
{
|
{
|
||||||
rc = __sys_CreateDesktopA(lpszDesktop, NULL, NULL, dwFlags, dwDesiredAccess, NULL);
|
rc = __sys_CreateDesktopA(lpszDesktop, NULL, NULL, dwFlags, dwDesiredAccess, NULL);
|
||||||
if (rc)
|
//if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Sandboxie_Desktop)
|
|
||||||
return Sandboxie_Desktop;
|
|
||||||
SbieApi_Log(2205, L"CreateDesktop");
|
SbieApi_Log(2205, L"CreateDesktop");
|
||||||
return CreateEvent(NULL, FALSE, FALSE, NULL);
|
return CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2010,6 +2010,15 @@ _FX BOOLEAN Sxs_PreferExternal(THREAD_DATA *TlsData)
|
||||||
if (!TlsData->proc_image_path)
|
if (!TlsData->proc_image_path)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// KB5014019 breaks edge, it seams making edge start its child processes with
|
||||||
|
// PreferExternalManifest fixes the issue, but the main process must be loaded normally
|
||||||
|
// hence we have ExternalManifestHack that checks the parent and not the target
|
||||||
|
//
|
||||||
|
|
||||||
|
if (Config_GetSettingsForImageName_bool(L"ExternalManifestHack", FALSE))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
WCHAR *ptr1 = wcsrchr(TlsData->proc_image_path, L'\\');
|
WCHAR *ptr1 = wcsrchr(TlsData->proc_image_path, L'\\');
|
||||||
|
|
||||||
WCHAR value[16];
|
WCHAR value[16];
|
||||||
|
|
|
@ -605,7 +605,7 @@ void GuiServer::RunSlave(const WCHAR *cmdline)
|
||||||
// create window station
|
// create window station
|
||||||
//
|
//
|
||||||
|
|
||||||
if (! pThis->GetWindowStationAndDesktopName(NULL, NULL, NULL))
|
if (! pThis->GetWindowStationAndDesktopName(NULL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1190,7 +1190,7 @@ HANDLE GuiServer::GetJobObject(const WCHAR *boxname)
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
bool GuiServer::GetWindowStationAndDesktopName(WCHAR *out_name, HANDLE* out_winsta, HANDLE* out_desk)
|
bool GuiServer::GetWindowStationAndDesktopName(WCHAR *out_name)
|
||||||
{
|
{
|
||||||
static HWINSTA _hWinSta = NULL;
|
static HWINSTA _hWinSta = NULL;
|
||||||
static HDESK _hDesk = NULL;
|
static HDESK _hDesk = NULL;
|
||||||
|
@ -1205,8 +1205,6 @@ bool GuiServer::GetWindowStationAndDesktopName(WCHAR *out_name, HANDLE* out_wins
|
||||||
if (out_name) {
|
if (out_name) {
|
||||||
|
|
||||||
wcscpy(out_name, _CombinedName);
|
wcscpy(out_name, _CombinedName);
|
||||||
if (out_winsta) *out_winsta = _hWinSta;
|
|
||||||
if (out_desk) *out_desk = _hDesk;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,8 +1273,6 @@ bool GuiServer::GetWindowStationAndDesktopName(WCHAR *out_name, HANDLE* out_wins
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
||||||
if (out_winsta) *out_winsta = _hWinSta;
|
|
||||||
|
|
||||||
if (! SetProcessWindowStation(_hWinSta))
|
if (! SetProcessWindowStation(_hWinSta))
|
||||||
errlvl = 0x62;
|
errlvl = 0x62;
|
||||||
else {
|
else {
|
||||||
|
@ -1289,9 +1285,6 @@ bool GuiServer::GetWindowStationAndDesktopName(WCHAR *out_name, HANDLE* out_wins
|
||||||
const ACCESS_MASK DESKTOP_ALL_ACCESS = 0x1FF; // see WinUser.h
|
const ACCESS_MASK DESKTOP_ALL_ACCESS = 0x1FF; // see WinUser.h
|
||||||
_hDesk = CreateDesktop(desktop_name, NULL, NULL, 0,
|
_hDesk = CreateDesktop(desktop_name, NULL, NULL, 0,
|
||||||
DESKTOP_ALL_ACCESS | WRITE_OWNER, &sa);
|
DESKTOP_ALL_ACCESS | WRITE_OWNER, &sa);
|
||||||
|
|
||||||
if (out_desk) *out_desk = _hDesk;
|
|
||||||
|
|
||||||
if (! _hDesk)
|
if (! _hDesk)
|
||||||
errlvl = 0x63;
|
errlvl = 0x63;
|
||||||
|
|
||||||
|
@ -1474,9 +1467,7 @@ ULONG GuiServer::GetWindowStationSlave(SlaveArgs *args)
|
||||||
GUI_GET_WINDOW_STATION_RPL *rpl =
|
GUI_GET_WINDOW_STATION_RPL *rpl =
|
||||||
(GUI_GET_WINDOW_STATION_RPL *)args->rpl_buf;
|
(GUI_GET_WINDOW_STATION_RPL *)args->rpl_buf;
|
||||||
|
|
||||||
HANDLE sbie_winsta;
|
if (! GetWindowStationAndDesktopName(rpl->name)) {
|
||||||
HANDLE sbie_desk;
|
|
||||||
if (! GetWindowStationAndDesktopName(rpl->name, &sbie_winsta, &sbie_desk)) {
|
|
||||||
status = -1;
|
status = -1;
|
||||||
errlvl = 0x73;
|
errlvl = 0x73;
|
||||||
goto finish;
|
goto finish;
|
||||||
|
@ -1533,22 +1524,6 @@ ULONG GuiServer::GetWindowStationSlave(SlaveArgs *args)
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! DuplicateHandle(NtCurrentProcess(), sbie_winsta,
|
|
||||||
hProcess, (HANDLE *)&rpl->hsbie_winsta,
|
|
||||||
WINSTA_ALL_ACCESS | STANDARD_RIGHTS_REQUIRED, FALSE, 0)) {
|
|
||||||
status = GetLastError();
|
|
||||||
errlvl = 0x85;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! DuplicateHandle(NtCurrentProcess(), sbie_desk,
|
|
||||||
hProcess, (HANDLE *)&rpl->hsbie_desk,
|
|
||||||
0, FALSE, DUPLICATE_SAME_ACCESS)) {
|
|
||||||
status = GetLastError();
|
|
||||||
errlvl = 0x86;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -80,7 +80,7 @@ protected:
|
||||||
|
|
||||||
HANDLE GetJobObject(const WCHAR *boxname);
|
HANDLE GetJobObject(const WCHAR *boxname);
|
||||||
|
|
||||||
bool GetWindowStationAndDesktopName(WCHAR *out_name, HANDLE* out_winsta, HANDLE* out_desk);
|
bool GetWindowStationAndDesktopName(WCHAR *out_name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -94,8 +94,6 @@ struct tagGUI_GET_WINDOW_STATION_RPL
|
||||||
ULONG64 hwinsta;
|
ULONG64 hwinsta;
|
||||||
ULONG64 hdesk;
|
ULONG64 hdesk;
|
||||||
WCHAR name[96];
|
WCHAR name[96];
|
||||||
ULONG64 hsbie_winsta;
|
|
||||||
ULONG64 hsbie_desk;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct tagGUI_GET_WINDOW_STATION_RPL GUI_GET_WINDOW_STATION_RPL;
|
typedef struct tagGUI_GET_WINDOW_STATION_RPL GUI_GET_WINDOW_STATION_RPL;
|
||||||
|
|
|
@ -643,7 +643,7 @@ Tmpl.Url=https://www.microsoft.com/en-us/edge
|
||||||
Tmpl.Scan=s
|
Tmpl.Scan=s
|
||||||
Tmpl.ScanProduct=Microsoft Edge
|
Tmpl.ScanProduct=Microsoft Edge
|
||||||
Tmpl.ScanService=edgeupdate
|
Tmpl.ScanService=edgeupdate
|
||||||
PreferExternalManifest=msedge.exe,y
|
ExternalManifestHack=msedge.exe,y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Vivaldi
|
# Vivaldi
|
||||||
|
|
|
@ -1145,6 +1145,7 @@ SB_STATUS CSbieAPI::ReloadBoxes(bool bForceUpdate)
|
||||||
{
|
{
|
||||||
pBox = CSandBoxPtr(NewSandBox(BoxName, this));
|
pBox = CSandBoxPtr(NewSandBox(BoxName, this));
|
||||||
m_SandBoxes.insert(BoxName.toLower(), pBox);
|
m_SandBoxes.insert(BoxName.toLower(), pBox);
|
||||||
|
emit BoxAdded(pBox);
|
||||||
}
|
}
|
||||||
UpdateBoxPaths(pBox);
|
UpdateBoxPaths(pBox);
|
||||||
|
|
||||||
|
@ -1153,8 +1154,11 @@ SB_STATUS CSbieAPI::ReloadBoxes(bool bForceUpdate)
|
||||||
pBox->UpdateDetails();
|
pBox->UpdateDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(const QString& BoxName, OldSandBoxes.keys())
|
foreach(const QString & BoxName, OldSandBoxes.keys()) {
|
||||||
m_SandBoxes.remove(BoxName);
|
CSandBoxPtr pBox = m_SandBoxes.take(BoxName);
|
||||||
|
pBox->SetBoxPaths(QString(), QString(), QString());
|
||||||
|
emit BoxRemoved(pBox);
|
||||||
|
}
|
||||||
|
|
||||||
return SB_OK;
|
return SB_OK;
|
||||||
}
|
}
|
||||||
|
@ -1419,7 +1423,7 @@ SB_STATUS CSbieAPI::UpdateProcesses(bool bKeep, bool bAllSessions)
|
||||||
if (pBox->m_ActiveProcessCount == 0) {
|
if (pBox->m_ActiveProcessCount == 0) {
|
||||||
pBox->m_ActiveProcessCount = 1;
|
pBox->m_ActiveProcessCount = 1;
|
||||||
pBox->OpenBox();
|
pBox->OpenBox();
|
||||||
emit BoxOpened(pBox->GetName());
|
emit BoxOpened(pBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
pProcess->m_pBox = pBox.data();
|
pProcess->m_pBox = pBox.data();
|
||||||
|
@ -1459,7 +1463,7 @@ SB_STATUS CSbieAPI::UpdateProcesses(bool bKeep, bool bAllSessions)
|
||||||
pBox->m_ActiveProcessCount = ActiveProcessCount;
|
pBox->m_ActiveProcessCount = ActiveProcessCount;
|
||||||
if (WasBoxClosed) {
|
if (WasBoxClosed) {
|
||||||
pBox->CloseBox();
|
pBox->CloseBox();
|
||||||
emit BoxClosed(pBox->GetName());
|
emit BoxClosed(pBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2337,7 +2341,7 @@ CBoxedProcessPtr CSbieAPI::OnProcessBoxed(quint32 ProcessId, const QString& Path
|
||||||
if (pBox->m_ActiveProcessCount == 0) {
|
if (pBox->m_ActiveProcessCount == 0) {
|
||||||
pBox->m_ActiveProcessCount = 1;
|
pBox->m_ActiveProcessCount = 1;
|
||||||
pBox->OpenBox();
|
pBox->OpenBox();
|
||||||
emit BoxOpened(pBox->GetName());
|
emit BoxOpened(pBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
pProcess = CBoxedProcessPtr(NewBoxedProcess(ProcessId, pBox.data()));
|
pProcess = CBoxedProcessPtr(NewBoxedProcess(ProcessId, pBox.data()));
|
||||||
|
|
|
@ -158,8 +158,12 @@ signals:
|
||||||
void LogSbieMessage(quint32 MsgCode, const QStringList& MsgData, quint32 ProcessId);
|
void LogSbieMessage(quint32 MsgCode, const QStringList& MsgData, quint32 ProcessId);
|
||||||
void ProcessBoxed(quint32 ProcessId, const QString& Path, const QString& Box, quint32 ParentId);
|
void ProcessBoxed(quint32 ProcessId, const QString& Path, const QString& Box, quint32 ParentId);
|
||||||
void FileToRecover(const QString& BoxName, const QString& FilePath, const QString& BoxPath, quint32 ProcessId);
|
void FileToRecover(const QString& BoxName, const QString& FilePath, const QString& BoxPath, quint32 ProcessId);
|
||||||
void BoxOpened(const QString& BoxName);
|
|
||||||
void BoxClosed(const QString& BoxName);
|
void BoxAdded(const CSandBoxPtr& pBox);
|
||||||
|
void BoxOpened(const CSandBoxPtr& pBox);
|
||||||
|
void BoxClosed(const CSandBoxPtr& pBox);
|
||||||
|
void BoxRemoved(const CSandBoxPtr& pBox);
|
||||||
|
|
||||||
void NotAuthorized(bool bLoginRequired, bool &bRetry);
|
void NotAuthorized(bool bLoginRequired, bool &bRetry);
|
||||||
void QueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 RequestId, const QVariantMap& Data);
|
void QueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 RequestId, const QVariantMap& Data);
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,11 @@
|
||||||
CBoxMonitor::CBoxMonitor()
|
CBoxMonitor::CBoxMonitor()
|
||||||
{
|
{
|
||||||
m_bTerminate = false;
|
m_bTerminate = false;
|
||||||
start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CBoxMonitor::~CBoxMonitor()
|
CBoxMonitor::~CBoxMonitor()
|
||||||
{
|
{
|
||||||
m_bTerminate = true;
|
Stop();
|
||||||
if (!wait(10 * 1000))
|
|
||||||
terminate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBoxMonitor::Notify(const wstring& strDirectory)
|
void CBoxMonitor::Notify(const wstring& strDirectory)
|
||||||
|
@ -25,7 +22,7 @@ void CBoxMonitor::Notify(const wstring& strDirectory)
|
||||||
quint64 CBoxMonitor::CounDirSize(const QString& Directory, SBox* Box)
|
quint64 CBoxMonitor::CounDirSize(const QString& Directory, SBox* Box)
|
||||||
{
|
{
|
||||||
quint64 TotalSize = 0;
|
quint64 TotalSize = 0;
|
||||||
if (Box->pBox.isNull() || m_bTerminate)
|
if (m_bTerminate || Box->pBox.isNull())
|
||||||
return TotalSize;
|
return TotalSize;
|
||||||
|
|
||||||
QDir Dir(Directory);
|
QDir Dir(Directory);
|
||||||
|
@ -44,6 +41,8 @@ void CBoxMonitor::run()
|
||||||
{
|
{
|
||||||
while (!m_bTerminate)
|
while (!m_bTerminate)
|
||||||
{
|
{
|
||||||
|
Sleep(1000);
|
||||||
|
|
||||||
m_Mutex.lock();
|
m_Mutex.lock();
|
||||||
QList<QString> Keys = m_Boxes.keys();
|
QList<QString> Keys = m_Boxes.keys();
|
||||||
m_Mutex.unlock();
|
m_Mutex.unlock();
|
||||||
|
@ -62,12 +61,14 @@ void CBoxMonitor::run()
|
||||||
if (MinScanInterval > 30 * 60 * 1000)
|
if (MinScanInterval > 30 * 60 * 1000)
|
||||||
MinScanInterval = 30 * 60 * 1000;
|
MinScanInterval = 30 * 60 * 1000;
|
||||||
|
|
||||||
if (Box->Changed && (Box->Closed || Box->LastScan == 0 || (CurTick - Box->LastScan) > MinScanInterval)) {
|
if ((Box->Changed && (!Box->IsWatched || Box->LastScan == 0 || (CurTick - Box->LastScan) > MinScanInterval)) || Box->ForceUpdate) {
|
||||||
|
|
||||||
qDebug() << "Rescanning:" << Key << "(" + QDateTime::currentDateTime().toString() + ")";
|
qDebug() << "Rescanning:" << Key << "(" + QDateTime::currentDateTime().toString() + ")";
|
||||||
|
|
||||||
quint64 ScanStart = GetCurTick();
|
quint64 ScanStart = GetCurTick();
|
||||||
|
|
||||||
|
Box->ScanDuration = -1;
|
||||||
|
|
||||||
Box->TotalSize = CounDirSize(Key, Box);
|
Box->TotalSize = CounDirSize(Key, Box);
|
||||||
|
|
||||||
Box->ScanDuration = GetCurTick() - ScanStart;
|
Box->ScanDuration = GetCurTick() - ScanStart;
|
||||||
|
@ -79,6 +80,7 @@ void CBoxMonitor::run()
|
||||||
);
|
);
|
||||||
|
|
||||||
Box->Changed = false;
|
Box->Changed = false;
|
||||||
|
Box->ForceUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Mutex.lock();
|
m_Mutex.lock();
|
||||||
|
@ -86,14 +88,12 @@ void CBoxMonitor::run()
|
||||||
m_Boxes.remove(Key);
|
m_Boxes.remove(Key);
|
||||||
m_Mutex.unlock();
|
m_Mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
Sleep(1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBoxMonitor::UpdateBox(const QString& Path)
|
void CBoxMonitor::UpdateBox(const QString& Path)
|
||||||
{
|
{
|
||||||
// Note: this functin runs in the main thread
|
// Note: this private functin runs in the main thread
|
||||||
|
|
||||||
m_Mutex.lock();
|
m_Mutex.lock();
|
||||||
SBox Box = m_Boxes.value(Path);
|
SBox Box = m_Boxes.value(Path);
|
||||||
|
@ -103,27 +103,86 @@ void CBoxMonitor::UpdateBox(const QString& Path)
|
||||||
Box.pBox->SetSize(Box.TotalSize);
|
Box.pBox->SetSize(Box.TotalSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBoxMonitor::AddBox(CSandBoxPlus* pBox, bool AndWatch)
|
void CBoxMonitor::WatchBox(CSandBoxPlus* pBox)
|
||||||
{
|
{
|
||||||
QMutexLocker Lock(&m_Mutex);
|
QMutexLocker Lock(&m_Mutex);
|
||||||
|
if (!isRunning()) start();
|
||||||
|
|
||||||
m_Boxes[pBox->GetFileRoot()].pBox = pBox;
|
SBox& Box = m_Boxes[pBox->GetFileRoot()];
|
||||||
|
Box.pBox = pBox;
|
||||||
|
|
||||||
if (AndWatch) {
|
Box.IsWatched = true;
|
||||||
m_Boxes[pBox->GetFileRoot()].Closed = false;
|
AddDirectory(pBox->GetFileRoot().toStdWString().c_str(), true, FILE_NOTIFY_CHANGE_SIZE);
|
||||||
AddDirectory(pBox->GetFileRoot().toStdWString().c_str(), true, FILE_NOTIFY_CHANGE_SIZE);
|
}
|
||||||
|
|
||||||
|
void CBoxMonitor::ScanBox(CSandBoxPlus* pBox)
|
||||||
|
{
|
||||||
|
QMutexLocker Lock(&m_Mutex);
|
||||||
|
if (!isRunning()) start();
|
||||||
|
|
||||||
|
SBox& Box = m_Boxes[pBox->GetFileRoot()];
|
||||||
|
Box.pBox = pBox;
|
||||||
|
|
||||||
|
Box.ForceUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBoxMonitor::CloseBox(CSandBoxPlus* pBox)
|
||||||
|
{
|
||||||
|
QMutexLocker Lock(&m_Mutex);
|
||||||
|
if (!isRunning()) return;
|
||||||
|
|
||||||
|
SBox& Box = m_Boxes[pBox->GetFileRoot()];
|
||||||
|
|
||||||
|
if(Box.IsWatched)
|
||||||
|
DetachDirectory(pBox->GetFileRoot().toStdWString().c_str());
|
||||||
|
Box.IsWatched = false;
|
||||||
|
|
||||||
|
//Box.Changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBoxMonitor::RemoveBox(CSandBoxPlus* pBox)
|
||||||
|
{
|
||||||
|
QMutexLocker Lock(&m_Mutex);
|
||||||
|
if (!isRunning()) return;
|
||||||
|
|
||||||
|
auto I = m_Boxes.find(pBox->GetFileRoot());
|
||||||
|
if (I == m_Boxes.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(I->IsWatched)
|
||||||
|
DetachDirectory(pBox->GetFileRoot().toStdWString().c_str());
|
||||||
|
I->pBox.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBoxMonitor::IsScanPending(const CSandBoxPlus* pBox)
|
||||||
|
{
|
||||||
|
QMutexLocker Lock(&m_Mutex);
|
||||||
|
if (!isRunning()) false;
|
||||||
|
|
||||||
|
auto I = m_Boxes.find(pBox->GetFileRoot());
|
||||||
|
if (I == m_Boxes.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (I->Changed && !I->IsWatched) || I->ForceUpdate || I->ScanDuration == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBoxMonitor::Stop()
|
||||||
|
{
|
||||||
|
QMutexLocker Lock(&m_Mutex);
|
||||||
|
if (!isRunning()) return;
|
||||||
|
|
||||||
|
m_bTerminate = true;
|
||||||
|
|
||||||
|
if (!wait(10 * 1000)) {
|
||||||
|
terminate();
|
||||||
|
qDebug() << "Failed to stop monitor thread, terminating!!!";
|
||||||
}
|
}
|
||||||
else
|
|
||||||
m_Boxes[pBox->GetFileRoot()].Changed = true;
|
while (!m_Boxes.isEmpty()) {
|
||||||
}
|
SBox Box = m_Boxes.take(m_Boxes.firstKey());
|
||||||
|
if(Box.IsWatched && Box.pBox)
|
||||||
void CBoxMonitor::CloseBox(CSandBoxPlus* pBox, bool AndClear)
|
DetachDirectory(Box.pBox->GetFileRoot().toStdWString().c_str());
|
||||||
{
|
}
|
||||||
QMutexLocker Lock(&m_Mutex);
|
|
||||||
|
m_bTerminate = false;
|
||||||
if(AndClear)
|
|
||||||
m_Boxes[pBox->GetFileRoot()].pBox.clear();
|
|
||||||
m_Boxes[pBox->GetFileRoot()].Closed = true;
|
|
||||||
|
|
||||||
DetachDirectory(pBox->GetFileRoot().toStdWString().c_str());
|
|
||||||
}
|
}
|
|
@ -14,8 +14,14 @@ public:
|
||||||
|
|
||||||
virtual void run();
|
virtual void run();
|
||||||
|
|
||||||
void AddBox(CSandBoxPlus* pBox, bool AndWatch = false);
|
void WatchBox(CSandBoxPlus* pBox);
|
||||||
void CloseBox(CSandBoxPlus* pBox, bool AndClear = false);
|
void ScanBox(CSandBoxPlus* pBox);
|
||||||
|
void CloseBox(CSandBoxPlus* pBox);
|
||||||
|
void RemoveBox(CSandBoxPlus* pBox);
|
||||||
|
|
||||||
|
bool IsScanPending(const CSandBoxPlus* pBox);
|
||||||
|
|
||||||
|
void Stop();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void UpdateBox(const QString& Path);
|
void UpdateBox(const QString& Path);
|
||||||
|
@ -25,16 +31,18 @@ protected:
|
||||||
struct SBox
|
struct SBox
|
||||||
{
|
{
|
||||||
SBox() {
|
SBox() {
|
||||||
|
ForceUpdate = false;
|
||||||
Changed = false;
|
Changed = false;
|
||||||
Closed = false;
|
IsWatched = false;
|
||||||
LastScan = 0;
|
LastScan = 0;
|
||||||
ScanDuration = 0;
|
ScanDuration = 0;
|
||||||
TotalSize = 0;
|
TotalSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointer<CSandBoxPlus> pBox;
|
QPointer<CSandBoxPlus> pBox;
|
||||||
|
bool ForceUpdate;
|
||||||
bool Changed;
|
bool Changed;
|
||||||
bool Closed;
|
bool IsWatched;
|
||||||
quint64 LastScan;
|
quint64 LastScan;
|
||||||
quint64 ScanDuration;
|
quint64 ScanDuration;
|
||||||
|
|
||||||
|
|
|
@ -233,7 +233,7 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList, cons
|
||||||
{
|
{
|
||||||
case eName: Value = pBox->GetName(); break;
|
case eName: Value = pBox->GetName(); break;
|
||||||
case eStatus: Value = pBox.objectCast<CSandBoxPlus>()->GetStatusStr(); break;
|
case eStatus: Value = pBox.objectCast<CSandBoxPlus>()->GetStatusStr(); break;
|
||||||
case eInfo: Value = bWatchSize ? pBox.objectCast<CSandBoxPlus>()->GetSize() : 0; break;
|
case eInfo: Value = pBox.objectCast<CSandBoxPlus>()->IsEmptyCached() ? -2 : (bWatchSize ? pBox.objectCast<CSandBoxPlus>()->GetSize() : 0); break;
|
||||||
case ePath: Value = pBox->GetFileRoot(); break;
|
case ePath: Value = pBox->GetFileRoot(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList, cons
|
||||||
switch (section)
|
switch (section)
|
||||||
{
|
{
|
||||||
case eName: ColValue.Formatted = Value.toString().replace("_", " "); break;
|
case eName: ColValue.Formatted = Value.toString().replace("_", " "); break;
|
||||||
case eInfo: ColValue.Formatted = Value.toULongLong() > 0 ? FormatSize(Value.toULongLong()) : ""; break;
|
case eInfo: ColValue.Formatted = Value.toULongLong() == -2 ? tr("Empty") : (Value.toULongLong() > 0 ? FormatSize(Value.toULongLong()) : ""); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
|
@ -69,6 +69,7 @@
|
||||||
<file>IconOffCx.png</file>
|
<file>IconOffCx.png</file>
|
||||||
<file>Actions/Monitor.png</file>
|
<file>Actions/Monitor.png</file>
|
||||||
<file>SideLogo.png</file>
|
<file>SideLogo.png</file>
|
||||||
|
<file>Actions/Refresh.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/Boxes">
|
<qresource prefix="/Boxes">
|
||||||
<file alias="Empty3">Boxes/sandbox-b-empty.png</file>
|
<file alias="Empty3">Boxes/sandbox-b-empty.png</file>
|
||||||
|
|
|
@ -134,7 +134,7 @@ CSandMan::CSandMan(QWidget *parent)
|
||||||
|
|
||||||
theAPI = new CSbiePlusAPI(this);
|
theAPI = new CSbiePlusAPI(this);
|
||||||
connect(theAPI, SIGNAL(StatusChanged()), this, SLOT(OnStatusChanged()));
|
connect(theAPI, SIGNAL(StatusChanged()), this, SLOT(OnStatusChanged()));
|
||||||
connect(theAPI, SIGNAL(BoxClosed(const QString&)), this, SLOT(OnBoxClosed(const QString&)));
|
connect(theAPI, SIGNAL(BoxClosed(const CSandBoxPtr&)), this, SLOT(OnBoxClosed(const CSandBoxPtr&)));
|
||||||
|
|
||||||
m_RequestManager = NULL;
|
m_RequestManager = NULL;
|
||||||
|
|
||||||
|
@ -286,6 +286,7 @@ void CSandMan::LoadState()
|
||||||
restoreState(theConf->GetBlob("MainWindow/Window_State"));
|
restoreState(theConf->GetBlob("MainWindow/Window_State"));
|
||||||
//m_pBoxTree->restoreState(theConf->GetBlob("MainWindow/BoxTree_Columns"));
|
//m_pBoxTree->restoreState(theConf->GetBlob("MainWindow/BoxTree_Columns"));
|
||||||
m_pMessageLog->GetView()->header()->restoreState(theConf->GetBlob("MainWindow/LogList_Columns"));
|
m_pMessageLog->GetView()->header()->restoreState(theConf->GetBlob("MainWindow/LogList_Columns"));
|
||||||
|
m_pRecoveryLog->GetView()->header()->restoreState(theConf->GetBlob("MainWindow/RecoveryLog_Columns"));
|
||||||
m_pLogSplitter->restoreState(theConf->GetBlob("MainWindow/Log_Splitter"));
|
m_pLogSplitter->restoreState(theConf->GetBlob("MainWindow/Log_Splitter"));
|
||||||
m_pPanelSplitter->restoreState(theConf->GetBlob("MainWindow/Panel_Splitter"));
|
m_pPanelSplitter->restoreState(theConf->GetBlob("MainWindow/Panel_Splitter"));
|
||||||
m_pLogTabs->setCurrentIndex(theConf->GetInt("MainWindow/LogTab", 0));
|
m_pLogTabs->setCurrentIndex(theConf->GetInt("MainWindow/LogTab", 0));
|
||||||
|
@ -297,6 +298,7 @@ void CSandMan::StoreState()
|
||||||
theConf->SetBlob("MainWindow/Window_State", saveState());
|
theConf->SetBlob("MainWindow/Window_State", saveState());
|
||||||
//theConf->SetBlob("MainWindow/BoxTree_Columns", m_pBoxTree->saveState());
|
//theConf->SetBlob("MainWindow/BoxTree_Columns", m_pBoxTree->saveState());
|
||||||
theConf->SetBlob("MainWindow/LogList_Columns", m_pMessageLog->GetView()->header()->saveState());
|
theConf->SetBlob("MainWindow/LogList_Columns", m_pMessageLog->GetView()->header()->saveState());
|
||||||
|
theConf->SetBlob("MainWindow/RecoveryLog_Columns", m_pRecoveryLog->GetView()->header()->saveState());
|
||||||
theConf->SetBlob("MainWindow/Log_Splitter", m_pLogSplitter->saveState());
|
theConf->SetBlob("MainWindow/Log_Splitter", m_pLogSplitter->saveState());
|
||||||
theConf->SetBlob("MainWindow/Panel_Splitter", m_pPanelSplitter->saveState());
|
theConf->SetBlob("MainWindow/Panel_Splitter", m_pPanelSplitter->saveState());
|
||||||
theConf->SetValue("MainWindow/LogTab", m_pLogTabs->currentIndex());
|
theConf->SetValue("MainWindow/LogTab", m_pLogTabs->currentIndex());
|
||||||
|
@ -320,6 +322,10 @@ void CSandMan::CreateMenus()
|
||||||
m_pWndFinder = m_pMenuFile->addAction(CSandMan::GetIcon("finder"), tr("Window Finder"), this, SLOT(OnWndFinder()));
|
m_pWndFinder = m_pMenuFile->addAction(CSandMan::GetIcon("finder"), tr("Window Finder"), this, SLOT(OnWndFinder()));
|
||||||
m_pDisableForce = m_pMenuFile->addAction(tr("Pause Forcing Programs"), this, SLOT(OnDisableForce()));
|
m_pDisableForce = m_pMenuFile->addAction(tr("Pause Forcing Programs"), this, SLOT(OnDisableForce()));
|
||||||
m_pDisableForce->setCheckable(true);
|
m_pDisableForce->setCheckable(true);
|
||||||
|
m_pDisableRecovery = m_pMenuFile->addAction(tr("Disable File Recovery"));
|
||||||
|
m_pDisableRecovery->setCheckable(true);
|
||||||
|
m_pDisableMessages = m_pMenuFile->addAction(tr("Disable Message PopUp"));
|
||||||
|
m_pDisableMessages->setCheckable(true);
|
||||||
m_pMenuFile->addSeparator();
|
m_pMenuFile->addSeparator();
|
||||||
m_pMaintenance = m_pMenuFile->addMenu(CSandMan::GetIcon("Maintenance"), tr("&Maintenance"));
|
m_pMaintenance = m_pMenuFile->addMenu(CSandMan::GetIcon("Maintenance"), tr("&Maintenance"));
|
||||||
m_pConnect = m_pMaintenance->addAction(CSandMan::GetIcon("Connect"), tr("Connect"), this, SLOT(OnMaintenance()));
|
m_pConnect = m_pMaintenance->addAction(CSandMan::GetIcon("Connect"), tr("Connect"), this, SLOT(OnMaintenance()));
|
||||||
|
@ -367,7 +373,7 @@ void CSandMan::CreateMenus()
|
||||||
|
|
||||||
m_pMenuView->addSeparator();
|
m_pMenuView->addSeparator();
|
||||||
|
|
||||||
m_pRefreshAll = m_pMenuView->addAction(CSandMan::GetIcon("Recover"), tr("Refresh View"), this, SLOT(OnRefresh()));
|
m_pRefreshAll = m_pMenuView->addAction(CSandMan::GetIcon("Refresh"), tr("Refresh View"), this, SLOT(OnRefresh()));
|
||||||
m_pRefreshAll->setShortcut(QKeySequence("F5"));
|
m_pRefreshAll->setShortcut(QKeySequence("F5"));
|
||||||
m_pRefreshAll->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
m_pRefreshAll->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||||
this->addAction(m_pRefreshAll);
|
this->addAction(m_pRefreshAll);
|
||||||
|
@ -377,6 +383,7 @@ void CSandMan::CreateMenus()
|
||||||
m_pCleanUpMenu->addSeparator();
|
m_pCleanUpMenu->addSeparator();
|
||||||
m_pCleanUpMsgLog = m_pCleanUpMenu->addAction(tr("Cleanup Message Log"), this, SLOT(OnCleanUp()));
|
m_pCleanUpMsgLog = m_pCleanUpMenu->addAction(tr("Cleanup Message Log"), this, SLOT(OnCleanUp()));
|
||||||
m_pCleanUpTrace = m_pCleanUpMenu->addAction(tr("Cleanup Trace Log"), this, SLOT(OnCleanUp()));
|
m_pCleanUpTrace = m_pCleanUpMenu->addAction(tr("Cleanup Trace Log"), this, SLOT(OnCleanUp()));
|
||||||
|
m_pCleanUpRecovery = m_pCleanUpMenu->addAction(tr("Cleanup Recovery Log"), this, SLOT(OnCleanUp()));
|
||||||
|
|
||||||
m_pKeepTerminated = m_pMenuView->addAction(CSandMan::GetIcon("Keep"), tr("Keep terminated"), this, SLOT(OnProcView()));
|
m_pKeepTerminated = m_pMenuView->addAction(CSandMan::GetIcon("Keep"), tr("Keep terminated"), this, SLOT(OnProcView()));
|
||||||
m_pKeepTerminated->setCheckable(true);
|
m_pKeepTerminated->setCheckable(true);
|
||||||
|
@ -527,6 +534,22 @@ void CSandMan::CreateView()
|
||||||
m_pTraceView->AddAction(m_pCleanUpTrace);
|
m_pTraceView->AddAction(m_pCleanUpTrace);
|
||||||
|
|
||||||
m_pLogTabs->addTab(m_pTraceView, tr("Trace Log"));
|
m_pLogTabs->addTab(m_pTraceView, tr("Trace Log"));
|
||||||
|
|
||||||
|
|
||||||
|
// Recovery Log
|
||||||
|
m_pRecoveryLog = new CPanelWidgetEx();
|
||||||
|
|
||||||
|
//m_pRecoveryLog->GetView()->setItemDelegate(theGUI->GetItemDelegate());
|
||||||
|
((QTreeWidgetEx*)m_pRecoveryLog->GetView())->setHeaderLabels(tr("Time|Box Name|File Path").split("|"));
|
||||||
|
|
||||||
|
m_pRecoveryLog->GetMenu()->insertAction(m_pRecoveryLog->GetMenu()->actions()[0], m_pCleanUpMsgLog);
|
||||||
|
m_pRecoveryLog->GetMenu()->insertSeparator(m_pRecoveryLog->GetMenu()->actions()[0]);
|
||||||
|
|
||||||
|
m_pRecoveryLog->GetView()->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
m_pRecoveryLog->GetView()->setSortingEnabled(false);
|
||||||
|
|
||||||
|
m_pLogTabs->addTab(m_pRecoveryLog, tr("Recovery Log"));
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSandMan::CreateTrayMenu()
|
void CSandMan::CreateTrayMenu()
|
||||||
|
@ -581,6 +604,8 @@ void CSandMan::CreateTrayMenu()
|
||||||
m_pTrayMenu->addAction(m_pEmptyAll);
|
m_pTrayMenu->addAction(m_pEmptyAll);
|
||||||
m_pDisableForce2 = m_pTrayMenu->addAction(tr("Pause Forcing Programs"), this, SLOT(OnDisableForce2()));
|
m_pDisableForce2 = m_pTrayMenu->addAction(tr("Pause Forcing Programs"), this, SLOT(OnDisableForce2()));
|
||||||
m_pDisableForce2->setCheckable(true);
|
m_pDisableForce2->setCheckable(true);
|
||||||
|
m_pTrayMenu->addAction(m_pDisableRecovery);
|
||||||
|
m_pTrayMenu->addAction(m_pDisableMessages);
|
||||||
m_pTrayMenu->addSeparator();
|
m_pTrayMenu->addSeparator();
|
||||||
|
|
||||||
/*QWidgetAction* pBoxWidget = new QWidgetAction(m_pTrayMenu);
|
/*QWidgetAction* pBoxWidget = new QWidgetAction(m_pTrayMenu);
|
||||||
|
@ -1045,12 +1070,8 @@ finish:
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSandMan::OnBoxClosed(const QString& BoxName)
|
void CSandMan::OnBoxClosed(const CSandBoxPtr& pBox)
|
||||||
{
|
{
|
||||||
CSandBoxPtr pBox = theAPI->GetBoxByName(BoxName);
|
|
||||||
if (!pBox)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!pBox->GetBool("NeverDelete", false) && pBox->GetBool("AutoDelete", false) && !pBox->IsEmpty())
|
if (!pBox->GetBool("NeverDelete", false) && pBox->GetBool("AutoDelete", false) && !pBox->IsEmpty())
|
||||||
{
|
{
|
||||||
bool DeleteShapshots = false;
|
bool DeleteShapshots = false;
|
||||||
|
@ -1059,7 +1080,7 @@ void CSandMan::OnBoxClosed(const QString& BoxName)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(theConf->GetBool("Options/AutoBoxOpsNotify", false))
|
if(theConf->GetBool("Options/AutoBoxOpsNotify", false))
|
||||||
OnLogMessage(tr("Auto deleting content of %1").arg(BoxName), true);
|
OnLogMessage(tr("Auto deleting content of %1").arg(pBox->GetName()), true);
|
||||||
|
|
||||||
if (theConf->GetBool("Options/UseAsyncBoxOps", false))
|
if (theConf->GetBool("Options/UseAsyncBoxOps", false))
|
||||||
{
|
{
|
||||||
|
@ -1199,6 +1220,8 @@ void CSandMan::OnStatusChanged()
|
||||||
m_pBoxView->Clear();
|
m_pBoxView->Clear();
|
||||||
|
|
||||||
theAPI->WatchIni(false);
|
theAPI->WatchIni(false);
|
||||||
|
|
||||||
|
theAPI->StopMonitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pSupport->setVisible(g_Certificate.isEmpty());
|
m_pSupport->setVisible(g_Certificate.isEmpty());
|
||||||
|
@ -1295,9 +1318,10 @@ void CSandMan::OnLogMessage(const QString& Message, bool bNotify)
|
||||||
|
|
||||||
void CSandMan::OnLogSbieMessage(quint32 MsgCode, const QStringList& MsgData, quint32 ProcessId)
|
void CSandMan::OnLogSbieMessage(quint32 MsgCode, const QStringList& MsgData, quint32 ProcessId)
|
||||||
{
|
{
|
||||||
if ((MsgCode & 0xFFFF) == 2198) // file migration progress
|
if ((MsgCode & 0xFFFF) == 2198 ) // file migration progress
|
||||||
{
|
{
|
||||||
m_pPopUpWindow->ShowProgress(MsgCode, MsgData, ProcessId);
|
if (!m_pDisableMessages->isChecked())
|
||||||
|
m_pPopUpWindow->ShowProgress(MsgCode, MsgData, ProcessId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1307,7 +1331,7 @@ void CSandMan::OnLogSbieMessage(quint32 MsgCode, const QStringList& MsgData, qui
|
||||||
m_MissingTemplates.append(MsgData[2]);
|
m_MissingTemplates.append(MsgData[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((MsgCode & 0xFFFF) == 6004) // certificat error
|
if ((MsgCode & 0xFFFF) == 6004) // certificate error
|
||||||
{
|
{
|
||||||
static quint64 iLastCertWarning = 0;
|
static quint64 iLastCertWarning = 0;
|
||||||
if (iLastCertWarning + 60 < QDateTime::currentDateTime().toTime_t()) { // reset after 60 seconds
|
if (iLastCertWarning + 60 < QDateTime::currentDateTime().toTime_t()) { // reset after 60 seconds
|
||||||
|
@ -1359,7 +1383,7 @@ void CSandMan::OnLogSbieMessage(quint32 MsgCode, const QStringList& MsgData, qui
|
||||||
if ((MsgCode & 0xFFFF) == 2111) // process open denided
|
if ((MsgCode & 0xFFFF) == 2111) // process open denided
|
||||||
return; // dont pop that one up
|
return; // dont pop that one up
|
||||||
|
|
||||||
if(MsgCode != 0 && theConf->GetBool("Options/ShowNotifications", true))
|
if(MsgCode != 0 && theConf->GetBool("Options/ShowNotifications", true) && !m_pDisableMessages->isChecked())
|
||||||
m_pPopUpWindow->AddLogMessage(Message, MsgCode, MsgData, ProcessId);
|
m_pPopUpWindow->AddLogMessage(Message, MsgCode, MsgData, ProcessId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1389,6 +1413,23 @@ bool CSandMan::CheckCertificate()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSandMan::UpdateCertState()
|
||||||
|
{
|
||||||
|
g_CertInfo.State = theAPI->GetCertState();
|
||||||
|
|
||||||
|
g_CertInfo.about_to_expire = g_CertInfo.expirers_in_sec && g_CertInfo.expirers_in_sec < (60 * 60 * 24 * 30);
|
||||||
|
if (g_CertInfo.outdated)
|
||||||
|
OnLogMessage(tr("The supporter certificate is not valid for this build, please get an updated certificate"));
|
||||||
|
// outdated always implicates it is no longer valid
|
||||||
|
else if (g_CertInfo.expired) // may be still valid for the current and older builds
|
||||||
|
OnLogMessage(tr("The supporter certificate has expired%1, please get an updated certificate")
|
||||||
|
.arg(g_CertInfo.valid ? tr(", but it remains valid for the current build") : ""));
|
||||||
|
else if (g_CertInfo.about_to_expire)
|
||||||
|
OnLogMessage(tr("The supporter certificate will expire in %1 days, please get an updated certificate").arg(g_CertInfo.expirers_in_sec / (60 * 60 * 24)));
|
||||||
|
|
||||||
|
emit CertUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
void CSandMan::OnQueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 RequestId, const QVariantMap& Data)
|
void CSandMan::OnQueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 RequestId, const QVariantMap& Data)
|
||||||
{
|
{
|
||||||
m_pPopUpWindow->AddUserPrompt(RequestId, Data, ClientPid);
|
m_pPopUpWindow->AddUserPrompt(RequestId, Data, ClientPid);
|
||||||
|
@ -1397,7 +1438,7 @@ void CSandMan::OnQueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 Req
|
||||||
void CSandMan::OnFileToRecover(const QString& BoxName, const QString& FilePath, const QString& BoxPath, quint32 ProcessId)
|
void CSandMan::OnFileToRecover(const QString& BoxName, const QString& FilePath, const QString& BoxPath, quint32 ProcessId)
|
||||||
{
|
{
|
||||||
CSandBoxPtr pBox = theAPI->GetBoxByName(BoxName);
|
CSandBoxPtr pBox = theAPI->GetBoxByName(BoxName);
|
||||||
if (!pBox.isNull() && pBox.objectCast<CSandBoxPlus>()->IsRecoverySuspended())
|
if ((!pBox.isNull() && pBox.objectCast<CSandBoxPlus>()->IsRecoverySuspended()) || m_pDisableRecovery->isChecked())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (theConf->GetBool("Options/InstantRecovery", true))
|
if (theConf->GetBool("Options/InstantRecovery", true))
|
||||||
|
@ -1426,7 +1467,7 @@ bool CSandMan::OpenRecovery(const CSandBoxPtr& pBox, bool& DeleteShapshots, bool
|
||||||
// todo: resuse window?
|
// todo: resuse window?
|
||||||
}
|
}
|
||||||
|
|
||||||
CRecoveryWindow* pRecoveryWindow = new CRecoveryWindow(pBox, this);
|
CRecoveryWindow* pRecoveryWindow = new CRecoveryWindow(pBox, false, this);
|
||||||
if (pRecoveryWindow->FindFiles() == 0 && bCloseEmpty) {
|
if (pRecoveryWindow->FindFiles() == 0 && bCloseEmpty) {
|
||||||
delete pRecoveryWindow;
|
delete pRecoveryWindow;
|
||||||
}
|
}
|
||||||
|
@ -1441,29 +1482,29 @@ CRecoveryWindow* CSandMan::ShowRecovery(const CSandBoxPtr& pBox, bool bFind)
|
||||||
auto pBoxEx = pBox.objectCast<CSandBoxPlus>();
|
auto pBoxEx = pBox.objectCast<CSandBoxPlus>();
|
||||||
if (!pBoxEx) return false;
|
if (!pBoxEx) return false;
|
||||||
if (pBoxEx->m_pRecoveryWnd == NULL) {
|
if (pBoxEx->m_pRecoveryWnd == NULL) {
|
||||||
pBoxEx->m_pRecoveryWnd = new CRecoveryWindow(pBox);
|
pBoxEx->m_pRecoveryWnd = new CRecoveryWindow(pBox, bFind == false);
|
||||||
connect(pBoxEx->m_pRecoveryWnd, &CRecoveryWindow::Closed, [pBoxEx]() {
|
connect(pBoxEx->m_pRecoveryWnd, &CRecoveryWindow::Closed, [pBoxEx]() {
|
||||||
pBoxEx->m_pRecoveryWnd = NULL;
|
pBoxEx->m_pRecoveryWnd = NULL;
|
||||||
});
|
});
|
||||||
pBoxEx->m_pRecoveryWnd->show();
|
pBoxEx->m_pRecoveryWnd->show();
|
||||||
}
|
}
|
||||||
else {
|
/*else {
|
||||||
pBoxEx->m_pRecoveryWnd->setWindowState((pBoxEx->m_pRecoveryWnd->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
|
pBoxEx->m_pRecoveryWnd->setWindowState((pBoxEx->m_pRecoveryWnd->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
|
||||||
//SetForegroundWindow((HWND)pBoxEx->m_pRecoveryWnd->winId());
|
//SetForegroundWindow((HWND)pBoxEx->m_pRecoveryWnd->winId());
|
||||||
}
|
}*/
|
||||||
if(bFind)
|
if(bFind)
|
||||||
pBoxEx->m_pRecoveryWnd->FindFiles();
|
pBoxEx->m_pRecoveryWnd->FindFiles();
|
||||||
return pBoxEx->m_pRecoveryWnd;
|
return pBoxEx->m_pRecoveryWnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
SB_PROGRESS CSandMan::RecoverFiles(const QList<QPair<QString, QString>>& FileList, int Action)
|
SB_PROGRESS CSandMan::RecoverFiles(const QString& BoxName, const QList<QPair<QString, QString>>& FileList, int Action)
|
||||||
{
|
{
|
||||||
CSbieProgressPtr pProgress = CSbieProgressPtr(new CSbieProgress());
|
CSbieProgressPtr pProgress = CSbieProgressPtr(new CSbieProgress());
|
||||||
QtConcurrent::run(CSandMan::RecoverFilesAsync, pProgress, FileList, Action);
|
QtConcurrent::run(CSandMan::RecoverFilesAsync, pProgress, BoxName, FileList, Action);
|
||||||
return SB_PROGRESS(OP_ASYNC, pProgress);
|
return SB_PROGRESS(OP_ASYNC, pProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSandMan::RecoverFilesAsync(const CSbieProgressPtr& pProgress, const QList<QPair<QString, QString>>& FileList, int Action)
|
void CSandMan::RecoverFilesAsync(const CSbieProgressPtr& pProgress, const QString& BoxName, const QList<QPair<QString, QString>>& FileList, int Action)
|
||||||
{
|
{
|
||||||
SB_STATUS Status = SB_OK;
|
SB_STATUS Status = SB_OK;
|
||||||
|
|
||||||
|
@ -1506,6 +1547,13 @@ void CSandMan::RecoverFilesAsync(const CSbieProgressPtr& pProgress, const QList<
|
||||||
|
|
||||||
if (!QFile::rename(BoxPath, RecoveryPath))
|
if (!QFile::rename(BoxPath, RecoveryPath))
|
||||||
Unrecovered.append(BoxPath);
|
Unrecovered.append(BoxPath);
|
||||||
|
else {
|
||||||
|
QMetaObject::invokeMethod(theGUI, "OnFileRecovered", Qt::BlockingQueuedConnection, // show this question using the GUI thread
|
||||||
|
Q_ARG(QString, BoxName),
|
||||||
|
Q_ARG(QString, RecoveryPath),
|
||||||
|
Q_ARG(QString, BoxPath)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Unrecovered.isEmpty())
|
if (!Unrecovered.isEmpty())
|
||||||
|
@ -1528,6 +1576,21 @@ void CSandMan::RecoverFilesAsync(const CSbieProgressPtr& pProgress, const QList<
|
||||||
pProgress->Finish(Status);
|
pProgress->Finish(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSandMan::OnFileRecovered(const QString& BoxName, const QString& FilePath, const QString& BoxPath)
|
||||||
|
{
|
||||||
|
QTreeWidgetItem* pItem = new QTreeWidgetItem(); // Time|Box|FilePath
|
||||||
|
pItem->setText(0, QDateTime::currentDateTime().toString("hh:mm:ss.zzz"));
|
||||||
|
pItem->setText(1, BoxName);
|
||||||
|
pItem->setText(2, FilePath);
|
||||||
|
m_pRecoveryLog->GetTree()->addTopLevelItem(pItem);
|
||||||
|
|
||||||
|
m_pRecoveryLog->GetView()->verticalScrollBar()->setValue(m_pRecoveryLog->GetView()->verticalScrollBar()->maximum());
|
||||||
|
|
||||||
|
CSandBoxPtr pBox = theAPI->GetBoxByName(BoxName);
|
||||||
|
if (pBox)
|
||||||
|
pBox.objectCast<CSandBoxPlus>()->UpdateSize();
|
||||||
|
}
|
||||||
|
|
||||||
int CSandMan::ShowQuestion(const QString& question, const QString& checkBoxText, bool* checkBoxSetting, int buttons, int defaultButton)
|
int CSandMan::ShowQuestion(const QString& question, const QString& checkBoxText, bool* checkBoxSetting, int buttons, int defaultButton)
|
||||||
{
|
{
|
||||||
return CCheckableMessageBox::question(this, "Sandboxie-Plus", question, checkBoxText, checkBoxSetting, (QDialogButtonBox::StandardButtons)buttons, (QDialogButtonBox::StandardButton)defaultButton, QMessageBox::Question);
|
return CCheckableMessageBox::question(this, "Sandboxie-Plus", question, checkBoxText, checkBoxSetting, (QDialogButtonBox::StandardButtons)buttons, (QDialogButtonBox::StandardButton)defaultButton, QMessageBox::Question);
|
||||||
|
@ -1882,6 +1945,9 @@ void CSandMan::OnCleanUp()
|
||||||
if (sender() == m_pCleanUpTrace || sender() == m_pCleanUpButton)
|
if (sender() == m_pCleanUpTrace || sender() == m_pCleanUpButton)
|
||||||
m_pTraceView->Clear();
|
m_pTraceView->Clear();
|
||||||
|
|
||||||
|
if (sender() == m_pCleanUpRecovery || sender() == m_pCleanUpButton)
|
||||||
|
m_pRecoveryLog->GetTree()->clear();
|
||||||
|
|
||||||
if (sender() == m_pCleanUpProcesses || sender() == m_pCleanUpButton)
|
if (sender() == m_pCleanUpProcesses || sender() == m_pCleanUpButton)
|
||||||
theAPI->UpdateProcesses(false, m_pShowAllSessions->isChecked());
|
theAPI->UpdateProcesses(false, m_pShowAllSessions->isChecked());
|
||||||
}
|
}
|
||||||
|
@ -2399,443 +2465,6 @@ QString CSandMan::GetVersion()
|
||||||
return Version;
|
return Version;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSandMan::CheckForUpdates(bool bManual)
|
|
||||||
{
|
|
||||||
if (!m_pUpdateProgress.isNull())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_pUpdateProgress = CSbieProgressPtr(new CSbieProgress());
|
|
||||||
AddAsyncOp(m_pUpdateProgress);
|
|
||||||
m_pUpdateProgress->ShowMessage(tr("Checking for updates..."));
|
|
||||||
|
|
||||||
if (m_RequestManager == NULL)
|
|
||||||
m_RequestManager = new CNetworkAccessManager(30 * 1000, this);
|
|
||||||
|
|
||||||
|
|
||||||
QUrlQuery Query;
|
|
||||||
Query.addQueryItem("software", "sandboxie-plus");
|
|
||||||
//QString Branche = theConf->GetString("Options/ReleaseBranche");
|
|
||||||
//if (!Branche.isEmpty())
|
|
||||||
// Query.addQueryItem("branche", Branche);
|
|
||||||
//Query.addQueryItem("version", GetVersion());
|
|
||||||
Query.addQueryItem("version", QString::number(VERSION_MJR) + "." + QString::number(VERSION_MIN) + "." + QString::number(VERSION_REV) + "." + QString::number(VERSION_UPD));
|
|
||||||
Query.addQueryItem("system", "windows-" + QSysInfo::kernelVersion() + "-" + QSysInfo::currentCpuArchitecture());
|
|
||||||
Query.addQueryItem("language", QString::number(m_LanguageId));
|
|
||||||
|
|
||||||
QString UpdateKey = GetArguments(g_Certificate, L'\n', L':').value("UPDATEKEY");
|
|
||||||
if (UpdateKey.isEmpty())
|
|
||||||
UpdateKey = theAPI->GetGlobalSettings()->GetText("UpdateKey"); // theConf->GetString("Options/UpdateKey");
|
|
||||||
if (!UpdateKey.isEmpty())
|
|
||||||
Query.addQueryItem("update_key", UpdateKey);
|
|
||||||
Query.addQueryItem("auto", bManual ? "0" : "1");
|
|
||||||
|
|
||||||
QUrl Url("https://sandboxie-plus.com/update.php");
|
|
||||||
Url.setQuery(Query);
|
|
||||||
|
|
||||||
QNetworkRequest Request = QNetworkRequest(Url);
|
|
||||||
Request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
|
||||||
//Request.setRawHeader("Accept-Encoding", "gzip");
|
|
||||||
QNetworkReply* pReply = m_RequestManager->get(Request);
|
|
||||||
pReply->setProperty("manual", bManual);
|
|
||||||
connect(pReply, SIGNAL(finished()), this, SLOT(OnUpdateCheck()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::OnUpdateCheck()
|
|
||||||
{
|
|
||||||
if (m_pUpdateProgress.isNull())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
|
|
||||||
bool bManual = pReply->property("manual").toBool();
|
|
||||||
QByteArray Reply = pReply->readAll();
|
|
||||||
pReply->deleteLater();
|
|
||||||
|
|
||||||
m_pUpdateProgress->Finish(SB_OK);
|
|
||||||
m_pUpdateProgress.clear();
|
|
||||||
|
|
||||||
QVariantMap Data = QJsonDocument::fromJson(Reply).toVariant().toMap();
|
|
||||||
if (Data.isEmpty() || Data["error"].toBool())
|
|
||||||
{
|
|
||||||
QString Error = Data.isEmpty() ? tr("server not reachable") : Data["errorMsg"].toString();
|
|
||||||
OnLogMessage(tr("Failed to check for updates, error: %1").arg(Error), !bManual);
|
|
||||||
if (bManual)
|
|
||||||
QMessageBox::critical(this, "Sandboxie-Plus", tr("Failed to check for updates, error: %1").arg(Error));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bNothing = true;
|
|
||||||
|
|
||||||
QStringList IgnoredUpdates = theConf->GetStringList("Options/IgnoredUpdates");
|
|
||||||
|
|
||||||
QString UserMsg = Data["userMsg"].toString();
|
|
||||||
if (!UserMsg.isEmpty())
|
|
||||||
{
|
|
||||||
QString MsgHash = QCryptographicHash::hash(Data["userMsg"].toByteArray(), QCryptographicHash::Md5).toHex().left(8);
|
|
||||||
if (!IgnoredUpdates.contains(MsgHash))
|
|
||||||
{
|
|
||||||
QString FullMessage = UserMsg;
|
|
||||||
QString InfoUrl = Data["infoUrl"].toString();
|
|
||||||
if (!InfoUrl.isEmpty())
|
|
||||||
FullMessage += tr("<p>Do you want to go to the <a href=\"%1\">info page</a>?</p>").arg(InfoUrl);
|
|
||||||
|
|
||||||
CCheckableMessageBox mb(this);
|
|
||||||
mb.setWindowTitle("Sandboxie-Plus");
|
|
||||||
QIcon ico(QLatin1String(":/SandMan.png"));
|
|
||||||
mb.setIconPixmap(ico.pixmap(64, 64));
|
|
||||||
//mb.setTextFormat(Qt::RichText);
|
|
||||||
mb.setText(UserMsg);
|
|
||||||
mb.setCheckBoxText(tr("Don't show this announcement in the future."));
|
|
||||||
|
|
||||||
if (!InfoUrl.isEmpty()) {
|
|
||||||
mb.setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No);
|
|
||||||
mb.setDefaultButton(QDialogButtonBox::Yes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mb.setStandardButtons(QDialogButtonBox::Ok);
|
|
||||||
|
|
||||||
mb.exec();
|
|
||||||
|
|
||||||
if (mb.isChecked())
|
|
||||||
theConf->SetValue("Options/IgnoredUpdates", IgnoredUpdates << MsgHash);
|
|
||||||
|
|
||||||
if (mb.clickedStandardButton() == QDialogButtonBox::Yes)
|
|
||||||
{
|
|
||||||
QDesktopServices::openUrl(InfoUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
bNothing = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString VersionStr = Data["version"].toString();
|
|
||||||
if (!VersionStr.isEmpty()) //&& VersionStr != GetVersion())
|
|
||||||
{
|
|
||||||
UCHAR myVersion[4] = { VERSION_UPD, VERSION_REV, VERSION_MIN, VERSION_MJR }; // ntohl
|
|
||||||
ULONG MyVersion = *(ULONG*)&myVersion;
|
|
||||||
|
|
||||||
ULONG Version = 0;
|
|
||||||
QStringList Nums = VersionStr.split(".");
|
|
||||||
for (int i = 0, Bits = 24; i < Nums.count() && Bits >= 0; i++, Bits -= 8)
|
|
||||||
Version |= (Nums[i].toInt() & 0xFF) << Bits;
|
|
||||||
|
|
||||||
if (Version > MyVersion)
|
|
||||||
if (bManual || !IgnoredUpdates.contains(VersionStr)) // when checked manually always show result
|
|
||||||
{
|
|
||||||
bNothing = false;
|
|
||||||
//QDateTime Updated = QDateTime::fromTime_t(Data["updated"].toULongLong());
|
|
||||||
|
|
||||||
QString DownloadUrl = Data["downloadUrl"].toString();
|
|
||||||
// 'sha256'
|
|
||||||
// 'signature'
|
|
||||||
|
|
||||||
if (!DownloadUrl.isEmpty() && theConf->GetInt("Options/DownloadUpdates", 0) == 1)
|
|
||||||
DownloadUpdates(DownloadUrl, bManual);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QString UpdateMsg = Data["updateMsg"].toString();
|
|
||||||
QString UpdateUrl = Data["updateUrl"].toString();
|
|
||||||
|
|
||||||
QString FullMessage = UpdateMsg.isEmpty() ? tr("<p>There is a new version of Sandboxie-Plus available.<br /><font color='red'>New version:</font> <b>%1</b></p>").arg(VersionStr) : UpdateMsg;
|
|
||||||
if (!DownloadUrl.isEmpty())
|
|
||||||
FullMessage += tr("<p>Do you want to download the latest version?</p>");
|
|
||||||
else if (!UpdateUrl.isEmpty())
|
|
||||||
FullMessage += tr("<p>Do you want to go to the <a href=\"%1\">download page</a>?</p>").arg(UpdateUrl);
|
|
||||||
|
|
||||||
CCheckableMessageBox mb(this);
|
|
||||||
mb.setWindowTitle("Sandboxie-Plus");
|
|
||||||
QIcon ico(QLatin1String(":/SandMan.png"));
|
|
||||||
mb.setIconPixmap(ico.pixmap(64, 64));
|
|
||||||
//mb.setTextFormat(Qt::RichText);
|
|
||||||
mb.setText(FullMessage);
|
|
||||||
mb.setCheckBoxText(tr("Don't show this message anymore."));
|
|
||||||
mb.setCheckBoxVisible(!bManual);
|
|
||||||
|
|
||||||
if (!UpdateUrl.isEmpty() || !DownloadUrl.isEmpty()) {
|
|
||||||
mb.setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No);
|
|
||||||
mb.setDefaultButton(QDialogButtonBox::Yes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mb.setStandardButtons(QDialogButtonBox::Ok);
|
|
||||||
|
|
||||||
mb.exec();
|
|
||||||
|
|
||||||
if (mb.isChecked())
|
|
||||||
theConf->SetValue("Options/IgnoredUpdates", IgnoredUpdates << VersionStr);
|
|
||||||
|
|
||||||
if (mb.clickedStandardButton() == QDialogButtonBox::Yes)
|
|
||||||
{
|
|
||||||
if (!DownloadUrl.isEmpty())
|
|
||||||
DownloadUpdates(DownloadUrl, bManual);
|
|
||||||
else
|
|
||||||
QDesktopServices::openUrl(UpdateUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bNothing)
|
|
||||||
{
|
|
||||||
theConf->SetValue("Options/NextCheckForUpdates", QDateTime::currentDateTime().addDays(7).toTime_t());
|
|
||||||
|
|
||||||
if (bManual) {
|
|
||||||
QMessageBox::information(this, "Sandboxie-Plus", tr("No new updates found, your Sandboxie-Plus is up-to-date.\n"
|
|
||||||
"\nNote: The update check is often behind the latest GitHub release to ensure that only tested updates are offered."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::DownloadUpdates(const QString& DownloadUrl, bool bManual)
|
|
||||||
{
|
|
||||||
QNetworkRequest Request = QNetworkRequest(DownloadUrl);
|
|
||||||
Request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
|
||||||
//Request.setRawHeader("Accept-Encoding", "gzip");
|
|
||||||
QNetworkReply* pReply = m_RequestManager->get(Request);
|
|
||||||
pReply->setProperty("manual", bManual);
|
|
||||||
connect(pReply, SIGNAL(finished()), this, SLOT(OnUpdateDownload()));
|
|
||||||
connect(pReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(OnUpdateProgress(qint64, qint64)));
|
|
||||||
|
|
||||||
m_pUpdateProgress = CSbieProgressPtr(new CSbieProgress());
|
|
||||||
AddAsyncOp(m_pUpdateProgress);
|
|
||||||
m_pUpdateProgress->ShowMessage(tr("Downloading new version..."));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::OnUpdateProgress(qint64 bytes, qint64 bytesTotal)
|
|
||||||
{
|
|
||||||
if (bytesTotal != 0 && !m_pUpdateProgress.isNull())
|
|
||||||
m_pUpdateProgress->Progress(100 * bytes / bytesTotal);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::OnUpdateDownload()
|
|
||||||
{
|
|
||||||
if (m_pUpdateProgress.isNull())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QString TempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
|
||||||
if (TempDir.right(1) != "/")
|
|
||||||
TempDir += "/";
|
|
||||||
|
|
||||||
m_pUpdateProgress->Progress(-1);
|
|
||||||
|
|
||||||
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
|
|
||||||
bool bManual = pReply->property("manual").toBool();
|
|
||||||
quint64 Size = pReply->bytesAvailable();
|
|
||||||
QString Name = pReply->request().url().fileName();
|
|
||||||
if (Name.isEmpty() || Name.right(4).compare(".exe", Qt::CaseInsensitive) != 0)
|
|
||||||
Name = "Sandboxie-Plus-Install.exe";
|
|
||||||
|
|
||||||
QString FilePath = TempDir + Name;
|
|
||||||
|
|
||||||
QFile File(FilePath);
|
|
||||||
if (File.open(QFile::WriteOnly)) {
|
|
||||||
while (pReply->bytesAvailable() > 0)
|
|
||||||
File.write(pReply->read(4096));
|
|
||||||
File.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
pReply->deleteLater();
|
|
||||||
|
|
||||||
m_pUpdateProgress->Finish(SB_OK);
|
|
||||||
m_pUpdateProgress.clear();
|
|
||||||
|
|
||||||
if (File.size() != Size) {
|
|
||||||
QMessageBox::critical(this, "Sandboxie-Plus", tr("Failed to download update from: %1").arg(pReply->request().url().toString()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
theConf->SetValue("Options/PendingUpdatePackage", FilePath);
|
|
||||||
UpdateLabel();
|
|
||||||
|
|
||||||
if (bManual)
|
|
||||||
InstallUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::InstallUpdate()
|
|
||||||
{
|
|
||||||
QString FilePath = theConf->GetString("Options/PendingUpdatePackage");
|
|
||||||
if (FilePath.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QString Message = tr("<p>A Sandboxie-Plus update has been downloaded to the following location:</p><p><a href=\"%2\">%1</a></p><p>Do you want to begin the installation? If any programs are running sandboxed, they will be terminated.</p>")
|
|
||||||
.arg(FilePath).arg("File:///" + Split2(FilePath, "/", true).first);
|
|
||||||
int Ret = QMessageBox("Sandboxie-Plus", Message, QMessageBox::Information, QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape, QMessageBox::Cancel, this).exec();
|
|
||||||
if (Ret == QMessageBox::Cancel) {
|
|
||||||
theConf->DelValue("Options/PendingUpdatePackage");
|
|
||||||
UpdateLabel();
|
|
||||||
}
|
|
||||||
if (Ret != QMessageBox::Yes)
|
|
||||||
return;
|
|
||||||
|
|
||||||
theAPI->TerminateAll();
|
|
||||||
|
|
||||||
wstring wFile = FilePath.toStdWString();
|
|
||||||
|
|
||||||
SHELLEXECUTEINFO si = { 0 };
|
|
||||||
si.cbSize = sizeof(SHELLEXECUTEINFO);
|
|
||||||
si.fMask = SEE_MASK_NOCLOSEPROCESS;
|
|
||||||
si.hwnd = NULL;
|
|
||||||
si.lpVerb = L"runas";
|
|
||||||
si.lpFile = wFile.c_str();
|
|
||||||
si.lpParameters = L"/SILENT";
|
|
||||||
si.lpDirectory = NULL;
|
|
||||||
si.nShow = SW_SHOW;
|
|
||||||
si.hInstApp = NULL;
|
|
||||||
|
|
||||||
if (ShellExecuteEx(&si)) {
|
|
||||||
theConf->DelValue("Options/PendingUpdatePackage");
|
|
||||||
QApplication::quit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::OnHelp()
|
|
||||||
{
|
|
||||||
if (sender() == m_pSupport)
|
|
||||||
QDesktopServices::openUrl(QUrl("https://sandboxie-plus.com/go.php?to=donate"));
|
|
||||||
else if (sender() == m_pForum)
|
|
||||||
QDesktopServices::openUrl(QUrl("https://sandboxie-plus.com/go.php?to=sbie-forum"));
|
|
||||||
else if (sender() == m_pManual)
|
|
||||||
QDesktopServices::openUrl(QUrl("https://sandboxie-plus.com/go.php?to=sbie-docs"));
|
|
||||||
else
|
|
||||||
QDesktopServices::openUrl(QUrl("https://sandboxie-plus.com/go.php?to=patreon"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::OnAbout()
|
|
||||||
{
|
|
||||||
if (sender() == m_pAbout)
|
|
||||||
{
|
|
||||||
QString AboutCaption = tr(
|
|
||||||
"<h3>About Sandboxie-Plus</h3>"
|
|
||||||
"<p>Version %1</p>"
|
|
||||||
"<p>Copyright (c) 2020-2022 by DavidXanatos</p>"
|
|
||||||
).arg(GetVersion());
|
|
||||||
|
|
||||||
QString CertInfo;
|
|
||||||
if (!g_Certificate.isEmpty()) {
|
|
||||||
CertInfo = tr("This copy of Sandboxie+ is certified for: %1").arg(GetArguments(g_Certificate, L'\n', L':').value("NAME"));
|
|
||||||
} else {
|
|
||||||
CertInfo = tr("Sandboxie+ is free for personal and non-commercial use.");
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AboutText = tr(
|
|
||||||
"Sandboxie-Plus is an open source continuation of Sandboxie.<br />"
|
|
||||||
"Visit <a href=\"https://sandboxie-plus.com\">sandboxie-plus.com</a> for more information.<br />"
|
|
||||||
"<br />"
|
|
||||||
"%3<br />"
|
|
||||||
"<br />"
|
|
||||||
"Driver version: %1<br />"
|
|
||||||
"Features: %2<br />"
|
|
||||||
"<br />"
|
|
||||||
"Icons from <a href=\"https://icons8.com\">icons8.com</a>"
|
|
||||||
).arg(theAPI->GetVersion()).arg(theAPI->GetFeatureStr()).arg(CertInfo);
|
|
||||||
|
|
||||||
QMessageBox *msgBox = new QMessageBox(this);
|
|
||||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
msgBox->setWindowTitle(tr("About Sandboxie-Plus"));
|
|
||||||
msgBox->setText(AboutCaption);
|
|
||||||
msgBox->setInformativeText(AboutText);
|
|
||||||
|
|
||||||
QIcon ico(QLatin1String(":/SandMan.png"));
|
|
||||||
msgBox->setIconPixmap(ico.pixmap(128, 128));
|
|
||||||
|
|
||||||
SafeExec(msgBox);
|
|
||||||
}
|
|
||||||
else if (sender() == m_pAboutQt)
|
|
||||||
QMessageBox::aboutQt(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::UpdateCertState()
|
|
||||||
{
|
|
||||||
g_CertInfo.State = theAPI->GetCertState();
|
|
||||||
|
|
||||||
g_CertInfo.about_to_expire = g_CertInfo.expirers_in_sec && g_CertInfo.expirers_in_sec < (60*60*24*30);
|
|
||||||
if (g_CertInfo.outdated)
|
|
||||||
OnLogMessage(tr("The supporter certificate is not valid for this build, please get an updated certificate"));
|
|
||||||
// outdated always implicates it is no longer valid
|
|
||||||
else if (g_CertInfo.expired) // may be still valid for the current and older builds
|
|
||||||
OnLogMessage(tr("The supporter certificate has expired%1, please get an updated certificate")
|
|
||||||
.arg(g_CertInfo.valid ? tr(", but it remains valid for the current build") : ""));
|
|
||||||
else if(g_CertInfo.about_to_expire)
|
|
||||||
OnLogMessage(tr("The supporter certificate will expire in %1 days, please get an updated certificate").arg(g_CertInfo.expirers_in_sec / (60*60*24)));
|
|
||||||
|
|
||||||
emit CertUpdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::UpdateCert()
|
|
||||||
{
|
|
||||||
QString UpdateKey; // for now only patreons can update the cert automatically
|
|
||||||
if(GetArguments(g_Certificate, L'\n', L':').value("type").indexOf("PATREON") == 0)
|
|
||||||
UpdateKey = GetArguments(g_Certificate, L'\n', L':').value("UPDATEKEY");
|
|
||||||
if (UpdateKey.isEmpty()) {
|
|
||||||
OpenUrl("https://sandboxie-plus.com/go.php?to=sbie-get-cert");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_pUpdateProgress.isNull())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_pUpdateProgress = CSbieProgressPtr(new CSbieProgress());
|
|
||||||
AddAsyncOp(m_pUpdateProgress);
|
|
||||||
m_pUpdateProgress->ShowMessage(tr("Checking for certificate..."));
|
|
||||||
|
|
||||||
if (m_RequestManager == NULL)
|
|
||||||
m_RequestManager = new CNetworkAccessManager(30 * 1000, this);
|
|
||||||
|
|
||||||
|
|
||||||
QUrlQuery Query;
|
|
||||||
Query.addQueryItem("UpdateKey", UpdateKey);
|
|
||||||
|
|
||||||
QUrl Url("https://sandboxie-plus.com/get_cert.php");
|
|
||||||
Url.setQuery(Query);
|
|
||||||
|
|
||||||
QNetworkRequest Request = QNetworkRequest(Url);
|
|
||||||
Request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
|
||||||
//Request.setRawHeader("Accept-Encoding", "gzip");
|
|
||||||
QNetworkReply* pReply = m_RequestManager->get(Request);
|
|
||||||
connect(pReply, SIGNAL(finished()), this, SLOT(OnCertCheck()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::OnCertCheck()
|
|
||||||
{
|
|
||||||
if (m_pUpdateProgress.isNull())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
|
|
||||||
QByteArray Reply = pReply->readAll();
|
|
||||||
int Code = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
pReply->deleteLater();
|
|
||||||
|
|
||||||
m_pUpdateProgress->Finish(SB_OK);
|
|
||||||
m_pUpdateProgress.clear();
|
|
||||||
|
|
||||||
if (Code > 299 || Code < 200) {
|
|
||||||
QMessageBox::critical(this, "Sandboxie-Plus", tr("No certificate found on server!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Reply.replace("\r\n","\n").compare(g_Certificate.replace("\r\n","\n"), Qt::CaseInsensitive) == 0){
|
|
||||||
QMessageBox::information(this, "Sandboxie-Plus", tr("There is no updated certificate available."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString CertPath = theAPI->GetSbiePath() + "\\Certificate.dat";
|
|
||||||
QString TempPath = QDir::tempPath() + "/Sbie+Certificate.dat";
|
|
||||||
QFile CertFile(TempPath);
|
|
||||||
if (CertFile.open(QFile::WriteOnly)) {
|
|
||||||
CertFile.write(Reply);
|
|
||||||
CertFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowsMoveFile(TempPath.replace("/", "\\"), CertPath.replace("/", "\\"));
|
|
||||||
|
|
||||||
if (!theAPI->ReloadCert().IsError()) {
|
|
||||||
CSettingsWindow::LoadCertificate();
|
|
||||||
UpdateCertState();
|
|
||||||
}
|
|
||||||
else { // this should not happen
|
|
||||||
g_Certificate.clear();
|
|
||||||
g_CertInfo.State = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::SetUITheme()
|
void CSandMan::SetUITheme()
|
||||||
{
|
{
|
||||||
m_ThemeUpdatePending = false;
|
m_ThemeUpdatePending = false;
|
||||||
|
@ -2953,234 +2582,7 @@ QT_TRANSLATE_NOOP("CSandBox", "Merging folders: %1 >> %2"),
|
||||||
QT_TRANSLATE_NOOP("CSandBox", "Finishing Snapshot Merge..."),
|
QT_TRANSLATE_NOOP("CSandBox", "Finishing Snapshot Merge..."),
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// WinSpy based window finder
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include "SandManUpdate.cpp"
|
||||||
#include "Helpers/FindTool.h"
|
|
||||||
|
|
||||||
|
#include "SbieFindWnd.cpp"
|
||||||
typedef enum DEVICE_SCALE_FACTOR {
|
|
||||||
DEVICE_SCALE_FACTOR_INVALID = 0,
|
|
||||||
SCALE_100_PERCENT = 100,
|
|
||||||
SCALE_120_PERCENT = 120,
|
|
||||||
SCALE_125_PERCENT = 125,
|
|
||||||
SCALE_140_PERCENT = 140,
|
|
||||||
SCALE_150_PERCENT = 150,
|
|
||||||
SCALE_160_PERCENT = 160,
|
|
||||||
SCALE_175_PERCENT = 175,
|
|
||||||
SCALE_180_PERCENT = 180,
|
|
||||||
SCALE_200_PERCENT = 200,
|
|
||||||
SCALE_225_PERCENT = 225,
|
|
||||||
SCALE_250_PERCENT = 250,
|
|
||||||
SCALE_300_PERCENT = 300,
|
|
||||||
SCALE_350_PERCENT = 350,
|
|
||||||
SCALE_400_PERCENT = 400,
|
|
||||||
SCALE_450_PERCENT = 450,
|
|
||||||
SCALE_500_PERCENT = 500
|
|
||||||
} DEVICE_SCALE_FACTOR;
|
|
||||||
|
|
||||||
typedef HRESULT (CALLBACK *P_GetScaleFactorForMonitor)(HMONITOR, DEVICE_SCALE_FACTOR*);
|
|
||||||
|
|
||||||
UINT GetMonitorScaling(HWND hwnd)
|
|
||||||
{
|
|
||||||
static HINSTANCE shcore = LoadLibrary(L"Shcore.dll");
|
|
||||||
if (shcore != nullptr)
|
|
||||||
{
|
|
||||||
if (auto getScaleFactorForMonitor =
|
|
||||||
P_GetScaleFactorForMonitor(GetProcAddress(shcore, "GetScaleFactorForMonitor")))
|
|
||||||
{
|
|
||||||
HMONITOR monitor =
|
|
||||||
MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
|
||||||
|
|
||||||
DEVICE_SCALE_FACTOR Scale;
|
|
||||||
|
|
||||||
getScaleFactorForMonitor(monitor, &Scale);
|
|
||||||
|
|
||||||
return Scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define IDD_FINDER_TOOL 111
|
|
||||||
#define ID_FINDER_TARGET 112
|
|
||||||
#define ID_FINDER_EXPLAIN 113
|
|
||||||
#define ID_FINDER_RESULT 114
|
|
||||||
|
|
||||||
struct SFinderWndData {
|
|
||||||
int Scale;
|
|
||||||
HFONT hFont;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DS(x) ((x) * WndData.Scale / 100)
|
|
||||||
|
|
||||||
UINT CALLBACK FindProc(HWND hwndTool, UINT uCode, HWND hwnd)
|
|
||||||
{
|
|
||||||
ULONG pid;
|
|
||||||
if (uCode == WFN_END)
|
|
||||||
GetWindowThreadProcessId(hwnd, &pid);
|
|
||||||
else
|
|
||||||
pid = 0;
|
|
||||||
|
|
||||||
hwndTool = GetParent(hwndTool);
|
|
||||||
|
|
||||||
SFinderWndData &WndData = *(SFinderWndData*)GetWindowLongPtr(hwndTool, 0);
|
|
||||||
|
|
||||||
if (pid && pid != GetCurrentProcessId())
|
|
||||||
{
|
|
||||||
RECT rc;
|
|
||||||
GetWindowRect(hwndTool, &rc);
|
|
||||||
if (rc.bottom - rc.top <= DS(150))
|
|
||||||
SetWindowPos(hwndTool, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top + DS(70), SWP_SHOWWINDOW | SWP_NOMOVE);
|
|
||||||
|
|
||||||
CBoxedProcessPtr pProcess = theAPI->GetProcessById(pid);
|
|
||||||
if (!pProcess.isNull())
|
|
||||||
{
|
|
||||||
wstring result = CSandMan::tr("The selected window is running as part of program %1 in sandbox %2").arg(pProcess->GetProcessName()).arg(pProcess->GetBoxName()).toStdWString();
|
|
||||||
|
|
||||||
SetWindowText(GetDlgItem(hwndTool, ID_FINDER_RESULT), result.c_str());
|
|
||||||
//::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_YES_BOXED), SW_SHOW);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wstring result = CSandMan::tr("The selected window is not running as part of any sandboxed program.").toStdWString();
|
|
||||||
|
|
||||||
SetWindowText(GetDlgItem(hwndTool, ID_FINDER_RESULT), result.c_str());
|
|
||||||
//::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_NOT_BOXED), SW_SHOW);
|
|
||||||
}
|
|
||||||
::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_RESULT), SW_SHOW);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RECT rc;
|
|
||||||
GetWindowRect(hwndTool, &rc);
|
|
||||||
if (rc.bottom - rc.top > DS(150))
|
|
||||||
SetWindowPos(hwndTool, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top - DS(70), SWP_SHOWWINDOW | SWP_NOMOVE);
|
|
||||||
|
|
||||||
//::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_YES_BOXED), SW_HIDE);
|
|
||||||
//::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_NOT_BOXED), SW_HIDE);
|
|
||||||
::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_RESULT), SW_HIDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// hwnd: All window processes are passed the handle of the window
|
|
||||||
// that they belong to in hwnd.
|
|
||||||
// msg: Current message (e.g., WM_*) from the OS.
|
|
||||||
// wParam: First message parameter, note that these are more or less
|
|
||||||
// integers, but they are really just "data chunks" that
|
|
||||||
// you are expected to memcpy as raw data to float, etc.
|
|
||||||
// lParam: Second message parameter, same deal as above.
|
|
||||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
switch (msg)
|
|
||||||
{
|
|
||||||
case WM_CREATE:
|
|
||||||
{
|
|
||||||
CREATESTRUCT* createStruct = (CREATESTRUCT*)lParam;
|
|
||||||
SFinderWndData &WndData = *(SFinderWndData*)createStruct->lpCreateParams;
|
|
||||||
SetWindowLongPtr(hwnd, 0, (LONG_PTR)&WndData);
|
|
||||||
|
|
||||||
wstring info = CSandMan::tr("Drag the Finder Tool over a window to select it, then release the mouse to check if the window is sandboxed.").toStdWString();
|
|
||||||
|
|
||||||
CreateWindow(L"Static", L"", SS_BITMAP | SS_NOTIFY | WS_VISIBLE | WS_CHILD, DS(10), DS(10), DS(32), DS(32), hwnd, (HMENU)ID_FINDER_TARGET, NULL, NULL);
|
|
||||||
CreateWindow(L"Static", info.c_str(), WS_VISIBLE | WS_CHILD, DS(60), DS(10), DS(180), DS(85), hwnd, (HMENU)ID_FINDER_EXPLAIN, NULL, NULL);
|
|
||||||
CreateWindow(L"Static", L"", WS_CHILD, DS(60), DS(100), DS(180), DS(50), hwnd, (HMENU)ID_FINDER_RESULT, NULL, NULL);
|
|
||||||
|
|
||||||
WndData.hFont = CreateFont(DS(13), 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Tahoma"));
|
|
||||||
if (WndData.hFont) {
|
|
||||||
SendMessage(GetDlgItem(hwnd, ID_FINDER_EXPLAIN), WM_SETFONT, (WPARAM)WndData.hFont, TRUE);
|
|
||||||
SendMessage(GetDlgItem(hwnd, ID_FINDER_RESULT), WM_SETFONT, (WPARAM)WndData.hFont, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
MakeFinderTool(GetDlgItem(hwnd, ID_FINDER_TARGET), FindProc);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_CLOSE:
|
|
||||||
SFinderWndData &WndData = *(SFinderWndData*)GetWindowLongPtr(hwnd, 0);
|
|
||||||
|
|
||||||
if (WndData.hFont) DeleteObject(WndData.hFont);
|
|
||||||
|
|
||||||
//DestroyWindow(hwnd);
|
|
||||||
PostQuitMessage(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD WINAPI FinderThreadFunc(LPVOID lpParam)
|
|
||||||
{
|
|
||||||
MSG msg;
|
|
||||||
WNDCLASS mainWindowClass = { 0 };
|
|
||||||
|
|
||||||
HINSTANCE hInstance = NULL;
|
|
||||||
|
|
||||||
// You can set the main window name to anything, but
|
|
||||||
// typically you should prefix custom window classes
|
|
||||||
// with something that makes it unique.
|
|
||||||
mainWindowClass.lpszClassName = TEXT("SBp.WndFinder");
|
|
||||||
|
|
||||||
mainWindowClass.hInstance = hInstance;
|
|
||||||
mainWindowClass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
|
||||||
mainWindowClass.lpfnWndProc = WndProc;
|
|
||||||
mainWindowClass.hCursor = LoadCursor(0, IDC_ARROW);
|
|
||||||
|
|
||||||
mainWindowClass.cbWndExtra = sizeof(void*); // SFinderWndData
|
|
||||||
|
|
||||||
RegisterClass(&mainWindowClass);
|
|
||||||
|
|
||||||
// Notes:
|
|
||||||
// - The classname identifies the TYPE of the window. Not a C type.
|
|
||||||
// This is a (TCHAR*) ID that Windows uses internally.
|
|
||||||
// - The window name is really just the window text, this is
|
|
||||||
// commonly used for captions, including the title
|
|
||||||
// bar of the window itself.
|
|
||||||
// - parentHandle is considered the "owner" of this
|
|
||||||
// window. MessageBoxes can use HWND_MESSAGE to
|
|
||||||
// free them of any window.
|
|
||||||
// - menuHandle: hMenu specifies the child-window identifier,
|
|
||||||
// an integer value used by a dialog box
|
|
||||||
// control to notify its parent about events.
|
|
||||||
// The application determines the child-window
|
|
||||||
// identifier; it must be unique for all
|
|
||||||
// child windows with the same parent window.
|
|
||||||
|
|
||||||
SFinderWndData WndData;
|
|
||||||
WndData.Scale = GetMonitorScaling(MainWndHandle);
|
|
||||||
|
|
||||||
HWND hwnd = CreateWindow(mainWindowClass.lpszClassName, CSandMan::tr("Sandboxie-Plus - Window Finder").toStdWString().c_str()
|
|
||||||
, WS_SYSMENU | WS_CAPTION | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, DS(275), DS(135), NULL, 0, hInstance, &WndData);
|
|
||||||
|
|
||||||
while (GetMessage(&msg, NULL, 0, 0))
|
|
||||||
{
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int)msg.wParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSandMan::OnWndFinder()
|
|
||||||
{
|
|
||||||
m_pWndFinder->setEnabled(false);
|
|
||||||
|
|
||||||
HANDLE hThread = CreateThread(NULL, 0, FinderThreadFunc, NULL, 0, NULL);
|
|
||||||
|
|
||||||
QWinEventNotifier* finishedNotifier = new QWinEventNotifier(hThread);
|
|
||||||
finishedNotifier->setEnabled(true);
|
|
||||||
connect(finishedNotifier, &QWinEventNotifier::activated, this, [finishedNotifier, this, hThread]() {
|
|
||||||
CloseHandle(hThread);
|
|
||||||
|
|
||||||
m_pWndFinder->setEnabled(true);
|
|
||||||
|
|
||||||
finishedNotifier->setEnabled(false);
|
|
||||||
finishedNotifier->deleteLater();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
|
|
||||||
static QString GetVersion();
|
static QString GetVersion();
|
||||||
|
|
||||||
SB_PROGRESS RecoverFiles(const QList<QPair<QString, QString>>& FileList, int Action = 0);
|
SB_PROGRESS RecoverFiles(const QString& BoxName, const QList<QPair<QString, QString>>& FileList, int Action = 0);
|
||||||
|
|
||||||
enum EDelMode {
|
enum EDelMode {
|
||||||
eDefault,
|
eDefault,
|
||||||
|
@ -81,7 +81,7 @@ protected:
|
||||||
SB_STATUS DisconnectSbie();
|
SB_STATUS DisconnectSbie();
|
||||||
SB_RESULT(void*) StopSbie(bool andRemove = false);
|
SB_RESULT(void*) StopSbie(bool andRemove = false);
|
||||||
|
|
||||||
static void RecoverFilesAsync(const CSbieProgressPtr& pProgress, const QList<QPair<QString, QString>>& FileList, int Action = 0);
|
static void RecoverFilesAsync(const CSbieProgressPtr& pProgress, const QString& BoxName, const QList<QPair<QString, QString>>& FileList, int Action = 0);
|
||||||
|
|
||||||
QIcon GetTrayIcon(bool isConnected = true);
|
QIcon GetTrayIcon(bool isConnected = true);
|
||||||
QString GetTrayText(bool isConnected = true);
|
QString GetTrayText(bool isConnected = true);
|
||||||
|
@ -137,6 +137,7 @@ public slots:
|
||||||
|
|
||||||
void OnQueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 RequestId, const QVariantMap& Data);
|
void OnQueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 RequestId, const QVariantMap& Data);
|
||||||
void OnFileToRecover(const QString& BoxName, const QString& FilePath, const QString& BoxPath, quint32 ProcessId);
|
void OnFileToRecover(const QString& BoxName, const QString& FilePath, const QString& BoxPath, quint32 ProcessId);
|
||||||
|
void OnFileRecovered(const QString& BoxName, const QString& FilePath, const QString& BoxPath);
|
||||||
|
|
||||||
bool OpenRecovery(const CSandBoxPtr& pBox, bool& DeleteShapshots, bool bCloseEmpty = false);
|
bool OpenRecovery(const CSandBoxPtr& pBox, bool& DeleteShapshots, bool bCloseEmpty = false);
|
||||||
class CRecoveryWindow* ShowRecovery(const CSandBoxPtr& pBox, bool bFind = true);
|
class CRecoveryWindow* ShowRecovery(const CSandBoxPtr& pBox, bool bFind = true);
|
||||||
|
@ -153,7 +154,7 @@ public slots:
|
||||||
void OnAsyncProgress(int Progress);
|
void OnAsyncProgress(int Progress);
|
||||||
void OnCancelAsync();
|
void OnCancelAsync();
|
||||||
|
|
||||||
void OnBoxClosed(const QString& BoxName);
|
void OnBoxClosed(const CSandBoxPtr& pBox);
|
||||||
|
|
||||||
void CheckForUpdates(bool bManual = true);
|
void CheckForUpdates(bool bManual = true);
|
||||||
void DownloadUpdates(const QString& DownloadUrl, bool bManual);
|
void DownloadUpdates(const QString& DownloadUrl, bool bManual);
|
||||||
|
@ -236,6 +237,7 @@ private:
|
||||||
|
|
||||||
CPanelWidgetEx* m_pMessageLog;
|
CPanelWidgetEx* m_pMessageLog;
|
||||||
CTraceView* m_pTraceView;
|
CTraceView* m_pTraceView;
|
||||||
|
CPanelWidgetEx* m_pRecoveryLog;
|
||||||
|
|
||||||
|
|
||||||
QMenu* m_pMenuFile;
|
QMenu* m_pMenuFile;
|
||||||
|
@ -245,6 +247,8 @@ private:
|
||||||
QAction* m_pWndFinder;
|
QAction* m_pWndFinder;
|
||||||
QAction* m_pDisableForce;
|
QAction* m_pDisableForce;
|
||||||
QAction* m_pDisableForce2;
|
QAction* m_pDisableForce2;
|
||||||
|
QAction* m_pDisableRecovery;
|
||||||
|
QAction* m_pDisableMessages;
|
||||||
QMenu* m_pMaintenance;
|
QMenu* m_pMaintenance;
|
||||||
QAction* m_pConnect;
|
QAction* m_pConnect;
|
||||||
QAction* m_pDisconnect;
|
QAction* m_pDisconnect;
|
||||||
|
@ -272,6 +276,7 @@ private:
|
||||||
QAction* m_pCleanUpProcesses;
|
QAction* m_pCleanUpProcesses;
|
||||||
QAction* m_pCleanUpMsgLog;
|
QAction* m_pCleanUpMsgLog;
|
||||||
QAction* m_pCleanUpTrace;
|
QAction* m_pCleanUpTrace;
|
||||||
|
QAction* m_pCleanUpRecovery;
|
||||||
QToolButton* m_pCleanUpButton;
|
QToolButton* m_pCleanUpButton;
|
||||||
QAction* m_pKeepTerminated;
|
QAction* m_pKeepTerminated;
|
||||||
QAction* m_pShowAllSessions;
|
QAction* m_pShowAllSessions;
|
||||||
|
|
|
@ -49,16 +49,6 @@ SOURCES += ./main.cpp \
|
||||||
./Helpers/WindowFromPointEx.cpp \
|
./Helpers/WindowFromPointEx.cpp \
|
||||||
./Windows/NewBoxWindow.cpp \
|
./Windows/NewBoxWindow.cpp \
|
||||||
./Windows/OptionsWindow.cpp \
|
./Windows/OptionsWindow.cpp \
|
||||||
./Windows/OptionsAccess.cpp \
|
|
||||||
./Windows/OptionsAdvanced.cpp \
|
|
||||||
./Windows/OptionsForce.cpp \
|
|
||||||
./Windows/OptionsGeneral.cpp \
|
|
||||||
./Windows/OptionsGrouping.cpp \
|
|
||||||
./Windows/OptionsNetwork.cpp \
|
|
||||||
./Windows/OptionsRecovery.cpp \
|
|
||||||
./Windows/OptionsStart.cpp \
|
|
||||||
./Windows/OptionsStop.cpp \
|
|
||||||
./Windows/OptionsTemplates.cpp \
|
|
||||||
./Windows/PopUpWindow.cpp \
|
./Windows/PopUpWindow.cpp \
|
||||||
./Windows/RecoveryWindow.cpp \
|
./Windows/RecoveryWindow.cpp \
|
||||||
./Windows/SettingsWindow.cpp \
|
./Windows/SettingsWindow.cpp \
|
||||||
|
|
|
@ -208,6 +208,18 @@
|
||||||
<ClCompile Include="Models\TraceModel.cpp" />
|
<ClCompile Include="Models\TraceModel.cpp" />
|
||||||
<ClCompile Include="Models\SbieModel.cpp" />
|
<ClCompile Include="Models\SbieModel.cpp" />
|
||||||
<ClCompile Include="SandMan.cpp" />
|
<ClCompile Include="SandMan.cpp" />
|
||||||
|
<ClCompile Include="SandManUpdate.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="SbieFindWnd.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="SbiePlusAPI.cpp" />
|
<ClCompile Include="SbiePlusAPI.cpp" />
|
||||||
<ClCompile Include="SbieProcess.cpp" />
|
<ClCompile Include="SbieProcess.cpp" />
|
||||||
<ClCompile Include="stdafx.cpp">
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
@ -220,16 +232,66 @@
|
||||||
<ClCompile Include="Views\TraceView.cpp" />
|
<ClCompile Include="Views\TraceView.cpp" />
|
||||||
<ClCompile Include="Windows\FileBrowserWindow.cpp" />
|
<ClCompile Include="Windows\FileBrowserWindow.cpp" />
|
||||||
<ClCompile Include="Windows\NewBoxWindow.cpp" />
|
<ClCompile Include="Windows\NewBoxWindow.cpp" />
|
||||||
<ClCompile Include="Windows\OptionsAccess.cpp" />
|
<ClCompile Include="Windows\OptionsAccess.cpp">
|
||||||
<ClCompile Include="Windows\OptionsAdvanced.cpp" />
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ClCompile Include="Windows\OptionsForce.cpp" />
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
<ClCompile Include="Windows\OptionsGeneral.cpp" />
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
<ClCompile Include="Windows\OptionsGrouping.cpp" />
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
<ClCompile Include="Windows\OptionsNetwork.cpp" />
|
</ClCompile>
|
||||||
<ClCompile Include="Windows\OptionsRecovery.cpp" />
|
<ClCompile Include="Windows\OptionsAdvanced.cpp">
|
||||||
<ClCompile Include="Windows\OptionsStart.cpp" />
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ClCompile Include="Windows\OptionsStop.cpp" />
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
<ClCompile Include="Windows\OptionsTemplates.cpp" />
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Windows\OptionsForce.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Windows\OptionsGeneral.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Windows\OptionsGrouping.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Windows\OptionsNetwork.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Windows\OptionsRecovery.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Windows\OptionsStart.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Windows\OptionsStop.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Windows\OptionsTemplates.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="Windows\OptionsWindow.cpp" />
|
<ClCompile Include="Windows\OptionsWindow.cpp" />
|
||||||
<ClCompile Include="Windows\PopUpWindow.cpp" />
|
<ClCompile Include="Windows\PopUpWindow.cpp" />
|
||||||
<ClCompile Include="Windows\RecoveryWindow.cpp" />
|
<ClCompile Include="Windows\RecoveryWindow.cpp" />
|
||||||
|
|
|
@ -162,6 +162,12 @@
|
||||||
<ClCompile Include="BoxMonitor.cpp">
|
<ClCompile Include="BoxMonitor.cpp">
|
||||||
<Filter>SandMan</Filter>
|
<Filter>SandMan</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="SbieFindWnd.cpp">
|
||||||
|
<Filter>SandMan</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="SandManUpdate.cpp">
|
||||||
|
<Filter>SandMan</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="stdafx.h">
|
<ClInclude Include="stdafx.h">
|
||||||
|
|
|
@ -0,0 +1,420 @@
|
||||||
|
|
||||||
|
void CSandMan::CheckForUpdates(bool bManual)
|
||||||
|
{
|
||||||
|
if (!m_pUpdateProgress.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_pUpdateProgress = CSbieProgressPtr(new CSbieProgress());
|
||||||
|
AddAsyncOp(m_pUpdateProgress);
|
||||||
|
m_pUpdateProgress->ShowMessage(tr("Checking for updates..."));
|
||||||
|
|
||||||
|
if (m_RequestManager == NULL)
|
||||||
|
m_RequestManager = new CNetworkAccessManager(30 * 1000, this);
|
||||||
|
|
||||||
|
|
||||||
|
QUrlQuery Query;
|
||||||
|
Query.addQueryItem("software", "sandboxie-plus");
|
||||||
|
//QString Branche = theConf->GetString("Options/ReleaseBranche");
|
||||||
|
//if (!Branche.isEmpty())
|
||||||
|
// Query.addQueryItem("branche", Branche);
|
||||||
|
//Query.addQueryItem("version", GetVersion());
|
||||||
|
Query.addQueryItem("version", QString::number(VERSION_MJR) + "." + QString::number(VERSION_MIN) + "." + QString::number(VERSION_REV) + "." + QString::number(VERSION_UPD));
|
||||||
|
Query.addQueryItem("system", "windows-" + QSysInfo::kernelVersion() + "-" + QSysInfo::currentCpuArchitecture());
|
||||||
|
Query.addQueryItem("language", QString::number(m_LanguageId));
|
||||||
|
|
||||||
|
QString UpdateKey = GetArguments(g_Certificate, L'\n', L':').value("UPDATEKEY");
|
||||||
|
if (UpdateKey.isEmpty())
|
||||||
|
UpdateKey = theAPI->GetGlobalSettings()->GetText("UpdateKey"); // theConf->GetString("Options/UpdateKey");
|
||||||
|
if (!UpdateKey.isEmpty())
|
||||||
|
Query.addQueryItem("update_key", UpdateKey);
|
||||||
|
Query.addQueryItem("auto", bManual ? "0" : "1");
|
||||||
|
|
||||||
|
QUrl Url("https://sandboxie-plus.com/update.php");
|
||||||
|
Url.setQuery(Query);
|
||||||
|
|
||||||
|
QNetworkRequest Request = QNetworkRequest(Url);
|
||||||
|
Request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||||
|
//Request.setRawHeader("Accept-Encoding", "gzip");
|
||||||
|
QNetworkReply* pReply = m_RequestManager->get(Request);
|
||||||
|
pReply->setProperty("manual", bManual);
|
||||||
|
connect(pReply, SIGNAL(finished()), this, SLOT(OnUpdateCheck()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSandMan::OnUpdateCheck()
|
||||||
|
{
|
||||||
|
if (m_pUpdateProgress.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
|
||||||
|
bool bManual = pReply->property("manual").toBool();
|
||||||
|
QByteArray Reply = pReply->readAll();
|
||||||
|
pReply->deleteLater();
|
||||||
|
|
||||||
|
m_pUpdateProgress->Finish(SB_OK);
|
||||||
|
m_pUpdateProgress.clear();
|
||||||
|
|
||||||
|
QVariantMap Data = QJsonDocument::fromJson(Reply).toVariant().toMap();
|
||||||
|
if (Data.isEmpty() || Data["error"].toBool())
|
||||||
|
{
|
||||||
|
QString Error = Data.isEmpty() ? tr("server not reachable") : Data["errorMsg"].toString();
|
||||||
|
OnLogMessage(tr("Failed to check for updates, error: %1").arg(Error), !bManual);
|
||||||
|
if (bManual)
|
||||||
|
QMessageBox::critical(this, "Sandboxie-Plus", tr("Failed to check for updates, error: %1").arg(Error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bNothing = true;
|
||||||
|
|
||||||
|
QStringList IgnoredUpdates = theConf->GetStringList("Options/IgnoredUpdates");
|
||||||
|
|
||||||
|
QString UserMsg = Data["userMsg"].toString();
|
||||||
|
if (!UserMsg.isEmpty())
|
||||||
|
{
|
||||||
|
QString MsgHash = QCryptographicHash::hash(Data["userMsg"].toByteArray(), QCryptographicHash::Md5).toHex().left(8);
|
||||||
|
if (!IgnoredUpdates.contains(MsgHash))
|
||||||
|
{
|
||||||
|
QString FullMessage = UserMsg;
|
||||||
|
QString InfoUrl = Data["infoUrl"].toString();
|
||||||
|
if (!InfoUrl.isEmpty())
|
||||||
|
FullMessage += tr("<p>Do you want to go to the <a href=\"%1\">info page</a>?</p>").arg(InfoUrl);
|
||||||
|
|
||||||
|
CCheckableMessageBox mb(this);
|
||||||
|
mb.setWindowTitle("Sandboxie-Plus");
|
||||||
|
QIcon ico(QLatin1String(":/SandMan.png"));
|
||||||
|
mb.setIconPixmap(ico.pixmap(64, 64));
|
||||||
|
//mb.setTextFormat(Qt::RichText);
|
||||||
|
mb.setText(UserMsg);
|
||||||
|
mb.setCheckBoxText(tr("Don't show this announcement in the future."));
|
||||||
|
|
||||||
|
if (!InfoUrl.isEmpty()) {
|
||||||
|
mb.setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No);
|
||||||
|
mb.setDefaultButton(QDialogButtonBox::Yes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mb.setStandardButtons(QDialogButtonBox::Ok);
|
||||||
|
|
||||||
|
mb.exec();
|
||||||
|
|
||||||
|
if (mb.isChecked())
|
||||||
|
theConf->SetValue("Options/IgnoredUpdates", IgnoredUpdates << MsgHash);
|
||||||
|
|
||||||
|
if (mb.clickedStandardButton() == QDialogButtonBox::Yes)
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(InfoUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
bNothing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString VersionStr = Data["version"].toString();
|
||||||
|
if (!VersionStr.isEmpty()) //&& VersionStr != GetVersion())
|
||||||
|
{
|
||||||
|
UCHAR myVersion[4] = { VERSION_UPD, VERSION_REV, VERSION_MIN, VERSION_MJR }; // ntohl
|
||||||
|
ULONG MyVersion = *(ULONG*)&myVersion;
|
||||||
|
|
||||||
|
ULONG Version = 0;
|
||||||
|
QStringList Nums = VersionStr.split(".");
|
||||||
|
for (int i = 0, Bits = 24; i < Nums.count() && Bits >= 0; i++, Bits -= 8)
|
||||||
|
Version |= (Nums[i].toInt() & 0xFF) << Bits;
|
||||||
|
|
||||||
|
if (Version > MyVersion)
|
||||||
|
if (bManual || !IgnoredUpdates.contains(VersionStr)) // when checked manually always show result
|
||||||
|
{
|
||||||
|
bNothing = false;
|
||||||
|
//QDateTime Updated = QDateTime::fromTime_t(Data["updated"].toULongLong());
|
||||||
|
|
||||||
|
QString DownloadUrl = Data["downloadUrl"].toString();
|
||||||
|
// 'sha256'
|
||||||
|
// 'signature'
|
||||||
|
|
||||||
|
if (!DownloadUrl.isEmpty() && theConf->GetInt("Options/DownloadUpdates", 0) == 1)
|
||||||
|
DownloadUpdates(DownloadUrl, bManual);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QString UpdateMsg = Data["updateMsg"].toString();
|
||||||
|
QString UpdateUrl = Data["updateUrl"].toString();
|
||||||
|
|
||||||
|
QString FullMessage = UpdateMsg.isEmpty() ? tr("<p>There is a new version of Sandboxie-Plus available.<br /><font color='red'>New version:</font> <b>%1</b></p>").arg(VersionStr) : UpdateMsg;
|
||||||
|
if (!DownloadUrl.isEmpty())
|
||||||
|
FullMessage += tr("<p>Do you want to download the latest version?</p>");
|
||||||
|
else if (!UpdateUrl.isEmpty())
|
||||||
|
FullMessage += tr("<p>Do you want to go to the <a href=\"%1\">download page</a>?</p>").arg(UpdateUrl);
|
||||||
|
|
||||||
|
CCheckableMessageBox mb(this);
|
||||||
|
mb.setWindowTitle("Sandboxie-Plus");
|
||||||
|
QIcon ico(QLatin1String(":/SandMan.png"));
|
||||||
|
mb.setIconPixmap(ico.pixmap(64, 64));
|
||||||
|
//mb.setTextFormat(Qt::RichText);
|
||||||
|
mb.setText(FullMessage);
|
||||||
|
mb.setCheckBoxText(tr("Don't show this message anymore."));
|
||||||
|
mb.setCheckBoxVisible(!bManual);
|
||||||
|
|
||||||
|
if (!UpdateUrl.isEmpty() || !DownloadUrl.isEmpty()) {
|
||||||
|
mb.setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No);
|
||||||
|
mb.setDefaultButton(QDialogButtonBox::Yes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mb.setStandardButtons(QDialogButtonBox::Ok);
|
||||||
|
|
||||||
|
mb.exec();
|
||||||
|
|
||||||
|
if (mb.isChecked())
|
||||||
|
theConf->SetValue("Options/IgnoredUpdates", IgnoredUpdates << VersionStr);
|
||||||
|
|
||||||
|
if (mb.clickedStandardButton() == QDialogButtonBox::Yes)
|
||||||
|
{
|
||||||
|
if (!DownloadUrl.isEmpty())
|
||||||
|
DownloadUpdates(DownloadUrl, bManual);
|
||||||
|
else
|
||||||
|
QDesktopServices::openUrl(UpdateUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bNothing)
|
||||||
|
{
|
||||||
|
theConf->SetValue("Options/NextCheckForUpdates", QDateTime::currentDateTime().addDays(7).toTime_t());
|
||||||
|
|
||||||
|
if (bManual) {
|
||||||
|
QMessageBox::information(this, "Sandboxie-Plus", tr("No new updates found, your Sandboxie-Plus is up-to-date.\n"
|
||||||
|
"\nNote: The update check is often behind the latest GitHub release to ensure that only tested updates are offered."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSandMan::DownloadUpdates(const QString& DownloadUrl, bool bManual)
|
||||||
|
{
|
||||||
|
QNetworkRequest Request = QNetworkRequest(DownloadUrl);
|
||||||
|
Request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||||
|
//Request.setRawHeader("Accept-Encoding", "gzip");
|
||||||
|
QNetworkReply* pReply = m_RequestManager->get(Request);
|
||||||
|
pReply->setProperty("manual", bManual);
|
||||||
|
connect(pReply, SIGNAL(finished()), this, SLOT(OnUpdateDownload()));
|
||||||
|
connect(pReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(OnUpdateProgress(qint64, qint64)));
|
||||||
|
|
||||||
|
m_pUpdateProgress = CSbieProgressPtr(new CSbieProgress());
|
||||||
|
AddAsyncOp(m_pUpdateProgress);
|
||||||
|
m_pUpdateProgress->ShowMessage(tr("Downloading new version..."));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSandMan::OnUpdateProgress(qint64 bytes, qint64 bytesTotal)
|
||||||
|
{
|
||||||
|
if (bytesTotal != 0 && !m_pUpdateProgress.isNull())
|
||||||
|
m_pUpdateProgress->Progress(100 * bytes / bytesTotal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSandMan::OnUpdateDownload()
|
||||||
|
{
|
||||||
|
if (m_pUpdateProgress.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString TempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
||||||
|
if (TempDir.right(1) != "/")
|
||||||
|
TempDir += "/";
|
||||||
|
|
||||||
|
m_pUpdateProgress->Progress(-1);
|
||||||
|
|
||||||
|
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
|
||||||
|
bool bManual = pReply->property("manual").toBool();
|
||||||
|
quint64 Size = pReply->bytesAvailable();
|
||||||
|
QString Name = pReply->request().url().fileName();
|
||||||
|
if (Name.isEmpty() || Name.right(4).compare(".exe", Qt::CaseInsensitive) != 0)
|
||||||
|
Name = "Sandboxie-Plus-Install.exe";
|
||||||
|
|
||||||
|
QString FilePath = TempDir + Name;
|
||||||
|
|
||||||
|
QFile File(FilePath);
|
||||||
|
if (File.open(QFile::WriteOnly)) {
|
||||||
|
while (pReply->bytesAvailable() > 0)
|
||||||
|
File.write(pReply->read(4096));
|
||||||
|
File.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
pReply->deleteLater();
|
||||||
|
|
||||||
|
m_pUpdateProgress->Finish(SB_OK);
|
||||||
|
m_pUpdateProgress.clear();
|
||||||
|
|
||||||
|
if (File.size() != Size) {
|
||||||
|
QMessageBox::critical(this, "Sandboxie-Plus", tr("Failed to download update from: %1").arg(pReply->request().url().toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
theConf->SetValue("Options/PendingUpdatePackage", FilePath);
|
||||||
|
UpdateLabel();
|
||||||
|
|
||||||
|
if (bManual)
|
||||||
|
InstallUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSandMan::InstallUpdate()
|
||||||
|
{
|
||||||
|
QString FilePath = theConf->GetString("Options/PendingUpdatePackage");
|
||||||
|
if (FilePath.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString Message = tr("<p>A Sandboxie-Plus update has been downloaded to the following location:</p><p><a href=\"%2\">%1</a></p><p>Do you want to begin the installation? If any programs are running sandboxed, they will be terminated.</p>")
|
||||||
|
.arg(FilePath).arg("File:///" + Split2(FilePath, "/", true).first);
|
||||||
|
int Ret = QMessageBox("Sandboxie-Plus", Message, QMessageBox::Information, QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape, QMessageBox::Cancel, this).exec();
|
||||||
|
if (Ret == QMessageBox::Cancel) {
|
||||||
|
theConf->DelValue("Options/PendingUpdatePackage");
|
||||||
|
UpdateLabel();
|
||||||
|
}
|
||||||
|
if (Ret != QMessageBox::Yes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
theAPI->TerminateAll();
|
||||||
|
|
||||||
|
wstring wFile = FilePath.toStdWString();
|
||||||
|
|
||||||
|
SHELLEXECUTEINFO si = { 0 };
|
||||||
|
si.cbSize = sizeof(SHELLEXECUTEINFO);
|
||||||
|
si.fMask = SEE_MASK_NOCLOSEPROCESS;
|
||||||
|
si.hwnd = NULL;
|
||||||
|
si.lpVerb = L"runas";
|
||||||
|
si.lpFile = wFile.c_str();
|
||||||
|
si.lpParameters = L"/SILENT";
|
||||||
|
si.lpDirectory = NULL;
|
||||||
|
si.nShow = SW_SHOW;
|
||||||
|
si.hInstApp = NULL;
|
||||||
|
|
||||||
|
if (ShellExecuteEx(&si)) {
|
||||||
|
theConf->DelValue("Options/PendingUpdatePackage");
|
||||||
|
QApplication::quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSandMan::OnHelp()
|
||||||
|
{
|
||||||
|
if (sender() == m_pSupport)
|
||||||
|
QDesktopServices::openUrl(QUrl("https://sandboxie-plus.com/go.php?to=donate"));
|
||||||
|
else if (sender() == m_pForum)
|
||||||
|
QDesktopServices::openUrl(QUrl("https://sandboxie-plus.com/go.php?to=sbie-forum"));
|
||||||
|
else if (sender() == m_pManual)
|
||||||
|
QDesktopServices::openUrl(QUrl("https://sandboxie-plus.com/go.php?to=sbie-docs"));
|
||||||
|
else
|
||||||
|
QDesktopServices::openUrl(QUrl("https://sandboxie-plus.com/go.php?to=patreon"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSandMan::OnAbout()
|
||||||
|
{
|
||||||
|
if (sender() == m_pAbout)
|
||||||
|
{
|
||||||
|
QString AboutCaption = tr(
|
||||||
|
"<h3>About Sandboxie-Plus</h3>"
|
||||||
|
"<p>Version %1</p>"
|
||||||
|
"<p>Copyright (c) 2020-2022 by DavidXanatos</p>"
|
||||||
|
).arg(GetVersion());
|
||||||
|
|
||||||
|
QString CertInfo;
|
||||||
|
if (!g_Certificate.isEmpty()) {
|
||||||
|
CertInfo = tr("This copy of Sandboxie+ is certified for: %1").arg(GetArguments(g_Certificate, L'\n', L':').value("NAME"));
|
||||||
|
} else {
|
||||||
|
CertInfo = tr("Sandboxie+ is free for personal and non-commercial use.");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AboutText = tr(
|
||||||
|
"Sandboxie-Plus is an open source continuation of Sandboxie.<br />"
|
||||||
|
"Visit <a href=\"https://sandboxie-plus.com\">sandboxie-plus.com</a> for more information.<br />"
|
||||||
|
"<br />"
|
||||||
|
"%3<br />"
|
||||||
|
"<br />"
|
||||||
|
"Driver version: %1<br />"
|
||||||
|
"Features: %2<br />"
|
||||||
|
"<br />"
|
||||||
|
"Icons from <a href=\"https://icons8.com\">icons8.com</a>"
|
||||||
|
).arg(theAPI->GetVersion()).arg(theAPI->GetFeatureStr()).arg(CertInfo);
|
||||||
|
|
||||||
|
QMessageBox *msgBox = new QMessageBox(this);
|
||||||
|
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
msgBox->setWindowTitle(tr("About Sandboxie-Plus"));
|
||||||
|
msgBox->setText(AboutCaption);
|
||||||
|
msgBox->setInformativeText(AboutText);
|
||||||
|
|
||||||
|
QIcon ico(QLatin1String(":/SandMan.png"));
|
||||||
|
msgBox->setIconPixmap(ico.pixmap(128, 128));
|
||||||
|
|
||||||
|
SafeExec(msgBox);
|
||||||
|
}
|
||||||
|
else if (sender() == m_pAboutQt)
|
||||||
|
QMessageBox::aboutQt(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSandMan::UpdateCert()
|
||||||
|
{
|
||||||
|
QString UpdateKey; // for now only patreons can update the cert automatically
|
||||||
|
if(GetArguments(g_Certificate, L'\n', L':').value("type").indexOf("PATREON") == 0)
|
||||||
|
UpdateKey = GetArguments(g_Certificate, L'\n', L':').value("UPDATEKEY");
|
||||||
|
if (UpdateKey.isEmpty()) {
|
||||||
|
OpenUrl("https://sandboxie-plus.com/go.php?to=sbie-get-cert");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_pUpdateProgress.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_pUpdateProgress = CSbieProgressPtr(new CSbieProgress());
|
||||||
|
AddAsyncOp(m_pUpdateProgress);
|
||||||
|
m_pUpdateProgress->ShowMessage(tr("Checking for certificate..."));
|
||||||
|
|
||||||
|
if (m_RequestManager == NULL)
|
||||||
|
m_RequestManager = new CNetworkAccessManager(30 * 1000, this);
|
||||||
|
|
||||||
|
|
||||||
|
QUrlQuery Query;
|
||||||
|
Query.addQueryItem("UpdateKey", UpdateKey);
|
||||||
|
|
||||||
|
QUrl Url("https://sandboxie-plus.com/get_cert.php");
|
||||||
|
Url.setQuery(Query);
|
||||||
|
|
||||||
|
QNetworkRequest Request = QNetworkRequest(Url);
|
||||||
|
Request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||||
|
//Request.setRawHeader("Accept-Encoding", "gzip");
|
||||||
|
QNetworkReply* pReply = m_RequestManager->get(Request);
|
||||||
|
connect(pReply, SIGNAL(finished()), this, SLOT(OnCertCheck()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSandMan::OnCertCheck()
|
||||||
|
{
|
||||||
|
if (m_pUpdateProgress.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
|
||||||
|
QByteArray Reply = pReply->readAll();
|
||||||
|
int Code = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
pReply->deleteLater();
|
||||||
|
|
||||||
|
m_pUpdateProgress->Finish(SB_OK);
|
||||||
|
m_pUpdateProgress.clear();
|
||||||
|
|
||||||
|
if (Code > 299 || Code < 200) {
|
||||||
|
QMessageBox::critical(this, "Sandboxie-Plus", tr("No certificate found on server!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reply.replace("\r\n","\n").compare(g_Certificate.replace("\r\n","\n"), Qt::CaseInsensitive) == 0){
|
||||||
|
QMessageBox::information(this, "Sandboxie-Plus", tr("There is no updated certificate available."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CertPath = theAPI->GetSbiePath() + "\\Certificate.dat";
|
||||||
|
QString TempPath = QDir::tempPath() + "/Sbie+Certificate.dat";
|
||||||
|
QFile CertFile(TempPath);
|
||||||
|
if (CertFile.open(QFile::WriteOnly)) {
|
||||||
|
CertFile.write(Reply);
|
||||||
|
CertFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowsMoveFile(TempPath.replace("/", "\\"), CertPath.replace("/", "\\"));
|
||||||
|
|
||||||
|
if (!theAPI->ReloadCert().IsError()) {
|
||||||
|
CSettingsWindow::LoadCertificate();
|
||||||
|
UpdateCertState();
|
||||||
|
}
|
||||||
|
else { // this should not happen
|
||||||
|
g_Certificate.clear();
|
||||||
|
g_CertInfo.State = 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// WinSpy based window finder
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include "Helpers/FindTool.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum DEVICE_SCALE_FACTOR {
|
||||||
|
DEVICE_SCALE_FACTOR_INVALID = 0,
|
||||||
|
SCALE_100_PERCENT = 100,
|
||||||
|
SCALE_120_PERCENT = 120,
|
||||||
|
SCALE_125_PERCENT = 125,
|
||||||
|
SCALE_140_PERCENT = 140,
|
||||||
|
SCALE_150_PERCENT = 150,
|
||||||
|
SCALE_160_PERCENT = 160,
|
||||||
|
SCALE_175_PERCENT = 175,
|
||||||
|
SCALE_180_PERCENT = 180,
|
||||||
|
SCALE_200_PERCENT = 200,
|
||||||
|
SCALE_225_PERCENT = 225,
|
||||||
|
SCALE_250_PERCENT = 250,
|
||||||
|
SCALE_300_PERCENT = 300,
|
||||||
|
SCALE_350_PERCENT = 350,
|
||||||
|
SCALE_400_PERCENT = 400,
|
||||||
|
SCALE_450_PERCENT = 450,
|
||||||
|
SCALE_500_PERCENT = 500
|
||||||
|
} DEVICE_SCALE_FACTOR;
|
||||||
|
|
||||||
|
typedef HRESULT (CALLBACK *P_GetScaleFactorForMonitor)(HMONITOR, DEVICE_SCALE_FACTOR*);
|
||||||
|
|
||||||
|
UINT GetMonitorScaling(HWND hwnd)
|
||||||
|
{
|
||||||
|
static HINSTANCE shcore = LoadLibrary(L"Shcore.dll");
|
||||||
|
if (shcore != nullptr)
|
||||||
|
{
|
||||||
|
if (auto getScaleFactorForMonitor =
|
||||||
|
P_GetScaleFactorForMonitor(GetProcAddress(shcore, "GetScaleFactorForMonitor")))
|
||||||
|
{
|
||||||
|
HMONITOR monitor =
|
||||||
|
MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
||||||
|
|
||||||
|
DEVICE_SCALE_FACTOR Scale;
|
||||||
|
|
||||||
|
getScaleFactorForMonitor(monitor, &Scale);
|
||||||
|
|
||||||
|
return Scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define IDD_FINDER_TOOL 111
|
||||||
|
#define ID_FINDER_TARGET 112
|
||||||
|
#define ID_FINDER_EXPLAIN 113
|
||||||
|
#define ID_FINDER_RESULT 114
|
||||||
|
|
||||||
|
struct SFinderWndData {
|
||||||
|
int Scale;
|
||||||
|
HFONT hFont;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DS(x) ((x) * WndData.Scale / 100)
|
||||||
|
|
||||||
|
UINT CALLBACK FindProc(HWND hwndTool, UINT uCode, HWND hwnd)
|
||||||
|
{
|
||||||
|
ULONG pid;
|
||||||
|
if (uCode == WFN_END)
|
||||||
|
GetWindowThreadProcessId(hwnd, &pid);
|
||||||
|
else
|
||||||
|
pid = 0;
|
||||||
|
|
||||||
|
hwndTool = GetParent(hwndTool);
|
||||||
|
|
||||||
|
SFinderWndData &WndData = *(SFinderWndData*)GetWindowLongPtr(hwndTool, 0);
|
||||||
|
|
||||||
|
if (pid && pid != GetCurrentProcessId())
|
||||||
|
{
|
||||||
|
RECT rc;
|
||||||
|
GetWindowRect(hwndTool, &rc);
|
||||||
|
if (rc.bottom - rc.top <= DS(150))
|
||||||
|
SetWindowPos(hwndTool, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top + DS(70), SWP_SHOWWINDOW | SWP_NOMOVE);
|
||||||
|
|
||||||
|
CBoxedProcessPtr pProcess = theAPI->GetProcessById(pid);
|
||||||
|
if (!pProcess.isNull())
|
||||||
|
{
|
||||||
|
wstring result = CSandMan::tr("The selected window is running as part of program %1 in sandbox %2").arg(pProcess->GetProcessName()).arg(pProcess->GetBoxName()).toStdWString();
|
||||||
|
|
||||||
|
SetWindowText(GetDlgItem(hwndTool, ID_FINDER_RESULT), result.c_str());
|
||||||
|
//::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_YES_BOXED), SW_SHOW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wstring result = CSandMan::tr("The selected window is not running as part of any sandboxed program.").toStdWString();
|
||||||
|
|
||||||
|
SetWindowText(GetDlgItem(hwndTool, ID_FINDER_RESULT), result.c_str());
|
||||||
|
//::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_NOT_BOXED), SW_SHOW);
|
||||||
|
}
|
||||||
|
::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_RESULT), SW_SHOW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RECT rc;
|
||||||
|
GetWindowRect(hwndTool, &rc);
|
||||||
|
if (rc.bottom - rc.top > DS(150))
|
||||||
|
SetWindowPos(hwndTool, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top - DS(70), SWP_SHOWWINDOW | SWP_NOMOVE);
|
||||||
|
|
||||||
|
//::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_YES_BOXED), SW_HIDE);
|
||||||
|
//::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_NOT_BOXED), SW_HIDE);
|
||||||
|
::ShowWindow(GetDlgItem(hwndTool, ID_FINDER_RESULT), SW_HIDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// hwnd: All window processes are passed the handle of the window
|
||||||
|
// that they belong to in hwnd.
|
||||||
|
// msg: Current message (e.g., WM_*) from the OS.
|
||||||
|
// wParam: First message parameter, note that these are more or less
|
||||||
|
// integers, but they are really just "data chunks" that
|
||||||
|
// you are expected to memcpy as raw data to float, etc.
|
||||||
|
// lParam: Second message parameter, same deal as above.
|
||||||
|
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_CREATE:
|
||||||
|
{
|
||||||
|
CREATESTRUCT* createStruct = (CREATESTRUCT*)lParam;
|
||||||
|
SFinderWndData &WndData = *(SFinderWndData*)createStruct->lpCreateParams;
|
||||||
|
SetWindowLongPtr(hwnd, 0, (LONG_PTR)&WndData);
|
||||||
|
|
||||||
|
wstring info = CSandMan::tr("Drag the Finder Tool over a window to select it, then release the mouse to check if the window is sandboxed.").toStdWString();
|
||||||
|
|
||||||
|
CreateWindow(L"Static", L"", SS_BITMAP | SS_NOTIFY | WS_VISIBLE | WS_CHILD, DS(10), DS(10), DS(32), DS(32), hwnd, (HMENU)ID_FINDER_TARGET, NULL, NULL);
|
||||||
|
CreateWindow(L"Static", info.c_str(), WS_VISIBLE | WS_CHILD, DS(60), DS(10), DS(180), DS(85), hwnd, (HMENU)ID_FINDER_EXPLAIN, NULL, NULL);
|
||||||
|
CreateWindow(L"Static", L"", WS_CHILD, DS(60), DS(100), DS(180), DS(50), hwnd, (HMENU)ID_FINDER_RESULT, NULL, NULL);
|
||||||
|
|
||||||
|
WndData.hFont = CreateFont(DS(13), 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Tahoma"));
|
||||||
|
if (WndData.hFont) {
|
||||||
|
SendMessage(GetDlgItem(hwnd, ID_FINDER_EXPLAIN), WM_SETFONT, (WPARAM)WndData.hFont, TRUE);
|
||||||
|
SendMessage(GetDlgItem(hwnd, ID_FINDER_RESULT), WM_SETFONT, (WPARAM)WndData.hFont, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
MakeFinderTool(GetDlgItem(hwnd, ID_FINDER_TARGET), FindProc);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_CLOSE:
|
||||||
|
SFinderWndData &WndData = *(SFinderWndData*)GetWindowLongPtr(hwnd, 0);
|
||||||
|
|
||||||
|
if (WndData.hFont) DeleteObject(WndData.hFont);
|
||||||
|
|
||||||
|
//DestroyWindow(hwnd);
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI FinderThreadFunc(LPVOID lpParam)
|
||||||
|
{
|
||||||
|
MSG msg;
|
||||||
|
WNDCLASS mainWindowClass = { 0 };
|
||||||
|
|
||||||
|
HINSTANCE hInstance = NULL;
|
||||||
|
|
||||||
|
// You can set the main window name to anything, but
|
||||||
|
// typically you should prefix custom window classes
|
||||||
|
// with something that makes it unique.
|
||||||
|
mainWindowClass.lpszClassName = TEXT("SBp.WndFinder");
|
||||||
|
|
||||||
|
mainWindowClass.hInstance = hInstance;
|
||||||
|
mainWindowClass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
||||||
|
mainWindowClass.lpfnWndProc = WndProc;
|
||||||
|
mainWindowClass.hCursor = LoadCursor(0, IDC_ARROW);
|
||||||
|
|
||||||
|
mainWindowClass.cbWndExtra = sizeof(void*); // SFinderWndData
|
||||||
|
|
||||||
|
RegisterClass(&mainWindowClass);
|
||||||
|
|
||||||
|
// Notes:
|
||||||
|
// - The classname identifies the TYPE of the window. Not a C type.
|
||||||
|
// This is a (TCHAR*) ID that Windows uses internally.
|
||||||
|
// - The window name is really just the window text, this is
|
||||||
|
// commonly used for captions, including the title
|
||||||
|
// bar of the window itself.
|
||||||
|
// - parentHandle is considered the "owner" of this
|
||||||
|
// window. MessageBoxes can use HWND_MESSAGE to
|
||||||
|
// free them of any window.
|
||||||
|
// - menuHandle: hMenu specifies the child-window identifier,
|
||||||
|
// an integer value used by a dialog box
|
||||||
|
// control to notify its parent about events.
|
||||||
|
// The application determines the child-window
|
||||||
|
// identifier; it must be unique for all
|
||||||
|
// child windows with the same parent window.
|
||||||
|
|
||||||
|
SFinderWndData WndData;
|
||||||
|
WndData.Scale = GetMonitorScaling(MainWndHandle);
|
||||||
|
|
||||||
|
HWND hwnd = CreateWindow(mainWindowClass.lpszClassName, CSandMan::tr("Sandboxie-Plus - Window Finder").toStdWString().c_str()
|
||||||
|
, WS_SYSMENU | WS_CAPTION | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, DS(275), DS(135), NULL, 0, hInstance, &WndData);
|
||||||
|
|
||||||
|
while (GetMessage(&msg, NULL, 0, 0))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)msg.wParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSandMan::OnWndFinder()
|
||||||
|
{
|
||||||
|
m_pWndFinder->setEnabled(false);
|
||||||
|
|
||||||
|
HANDLE hThread = CreateThread(NULL, 0, FinderThreadFunc, NULL, 0, NULL);
|
||||||
|
|
||||||
|
QWinEventNotifier* finishedNotifier = new QWinEventNotifier(hThread);
|
||||||
|
finishedNotifier->setEnabled(true);
|
||||||
|
connect(finishedNotifier, &QWinEventNotifier::activated, this, [finishedNotifier, this, hThread]() {
|
||||||
|
CloseHandle(hThread);
|
||||||
|
|
||||||
|
m_pWndFinder->setEnabled(true);
|
||||||
|
|
||||||
|
finishedNotifier->setEnabled(false);
|
||||||
|
finishedNotifier->deleteLater();
|
||||||
|
});
|
||||||
|
}
|
|
@ -81,6 +81,11 @@ bool CSbiePlusAPI::IsRunningAsAdmin()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSbiePlusAPI::StopMonitor()
|
||||||
|
{
|
||||||
|
m_BoxMonitor->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// CSandBoxPlus
|
// CSandBoxPlus
|
||||||
//
|
//
|
||||||
|
@ -163,18 +168,29 @@ void CSandBoxPlus::UpdateDetails()
|
||||||
|
|
||||||
void CSandBoxPlus::SetBoxPaths(const QString& FilePath, const QString& RegPath, const QString& IpcPath)
|
void CSandBoxPlus::SetBoxPaths(const QString& FilePath, const QString& RegPath, const QString& IpcPath)
|
||||||
{
|
{
|
||||||
|
bool bPathChanged = (FilePath != m_FilePath);
|
||||||
|
|
||||||
|
if (bPathChanged && !m_FilePath.isEmpty())
|
||||||
|
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->RemoveBox(this);
|
||||||
|
|
||||||
CSandBox::SetBoxPaths(FilePath, RegPath, IpcPath);
|
CSandBox::SetBoxPaths(FilePath, RegPath, IpcPath);
|
||||||
|
|
||||||
|
if (m_FilePath.isEmpty()) {
|
||||||
|
m_IsEmpty = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_IsEmpty = IsEmpty();
|
m_IsEmpty = IsEmpty();
|
||||||
|
|
||||||
if (theConf->GetBool("Options/WatchBoxSize", false) && m_TotalSize == -1)
|
if (bPathChanged && theConf->GetBool("Options/WatchBoxSize", false) && m_TotalSize == -1)
|
||||||
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->AddBox(this);
|
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->ScanBox(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSandBoxPlus::UpdateSize()
|
void CSandBoxPlus::UpdateSize()
|
||||||
{
|
{
|
||||||
m_TotalSize = -1;
|
m_TotalSize = -1;
|
||||||
if(theConf->GetBool("Options/WatchBoxSize", false))
|
if(theConf->GetBool("Options/WatchBoxSize", false))
|
||||||
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->AddBox(this);
|
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->ScanBox(this);
|
||||||
|
|
||||||
m_IsEmpty = IsEmpty();
|
m_IsEmpty = IsEmpty();
|
||||||
}
|
}
|
||||||
|
@ -185,6 +201,11 @@ void CSandBoxPlus::SetSize(quint64 Size)
|
||||||
theConf->SetValue("SizeCache/" + m_Name, Size);
|
theConf->SetValue("SizeCache/" + m_Name, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSandBoxPlus::IsSizePending() const
|
||||||
|
{
|
||||||
|
return ((CSbiePlusAPI*)theAPI)->m_BoxMonitor->IsScanPending(this);
|
||||||
|
}
|
||||||
|
|
||||||
void CSandBoxPlus::OpenBox()
|
void CSandBoxPlus::OpenBox()
|
||||||
{
|
{
|
||||||
CSandBox::OpenBox();
|
CSandBox::OpenBox();
|
||||||
|
@ -192,7 +213,7 @@ void CSandBoxPlus::OpenBox()
|
||||||
m_IsEmpty = false;
|
m_IsEmpty = false;
|
||||||
|
|
||||||
if (theConf->GetBool("Options/WatchBoxSize", false))
|
if (theConf->GetBool("Options/WatchBoxSize", false))
|
||||||
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->AddBox(this, true);
|
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->WatchBox(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSandBoxPlus::CloseBox()
|
void CSandBoxPlus::CloseBox()
|
||||||
|
@ -206,7 +227,7 @@ void CSandBoxPlus::CloseBox()
|
||||||
|
|
||||||
SB_PROGRESS CSandBoxPlus::CleanBox()
|
SB_PROGRESS CSandBoxPlus::CleanBox()
|
||||||
{
|
{
|
||||||
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->CloseBox(this, true);
|
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->RemoveBox(this);
|
||||||
|
|
||||||
SB_PROGRESS Status = CSandBox::CleanBox();
|
SB_PROGRESS Status = CSandBox::CleanBox();
|
||||||
|
|
||||||
|
@ -242,8 +263,8 @@ QString CSandBoxPlus::GetStatusStr() const
|
||||||
|
|
||||||
QStringList Status;
|
QStringList Status;
|
||||||
|
|
||||||
if (m_IsEmpty)
|
//if (m_IsEmpty)
|
||||||
Status.append(tr("Empty"));
|
// Status.append(tr("Empty"));
|
||||||
|
|
||||||
if (m_bApplicationCompartment)
|
if (m_bApplicationCompartment)
|
||||||
Status.append(tr("Application Compartment"));
|
Status.append(tr("Application Compartment"));
|
||||||
|
|
|
@ -19,6 +19,8 @@ public:
|
||||||
|
|
||||||
virtual bool IsBusy() const { return m_JobCount > 0; }
|
virtual bool IsBusy() const { return m_JobCount > 0; }
|
||||||
|
|
||||||
|
virtual void StopMonitor();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class CSandBoxPlus;
|
friend class CSandBoxPlus;
|
||||||
|
|
||||||
|
@ -80,9 +82,12 @@ public:
|
||||||
virtual void SetLeaderProgram(const QString& ProgName, bool bSet);
|
virtual void SetLeaderProgram(const QString& ProgName, bool bSet);
|
||||||
virtual int IsLeaderProgram(const QString& ProgName);
|
virtual int IsLeaderProgram(const QString& ProgName);
|
||||||
|
|
||||||
|
virtual bool IsEmptyCached() const { return m_IsEmpty; }
|
||||||
|
|
||||||
virtual void UpdateSize();
|
virtual void UpdateSize();
|
||||||
virtual quint64 GetSize() const { if(m_TotalSize == -1) return 0; return m_TotalSize; }
|
virtual quint64 GetSize() const { if(m_TotalSize == -1) return 0; return m_TotalSize; }
|
||||||
virtual void SetSize(quint64 Size); //{ m_TotalSize = Size; }
|
virtual void SetSize(quint64 Size); //{ m_TotalSize = Size; }
|
||||||
|
virtual bool IsSizePending() const;
|
||||||
|
|
||||||
virtual bool IsRecoverySuspended() const { return m_SuspendRecovery; }
|
virtual bool IsRecoverySuspended() const { return m_SuspendRecovery; }
|
||||||
virtual void SetSuspendRecovery(bool bSet = true) { m_SuspendRecovery = bSet; }
|
virtual void SetSuspendRecovery(bool bSet = true) { m_SuspendRecovery = bSet; }
|
||||||
|
@ -107,7 +112,7 @@ public:
|
||||||
class COptionsWindow* m_pOptionsWnd;
|
class COptionsWindow* m_pOptionsWnd;
|
||||||
class CRecoveryWindow* m_pRecoveryWnd;
|
class CRecoveryWindow* m_pRecoveryWnd;
|
||||||
|
|
||||||
bool IsBusy() const { return !m_JobQueue.isEmpty(); }
|
bool IsBusy() const { return IsSizePending() || !m_JobQueue.isEmpty(); }
|
||||||
SB_STATUS DeleteContentAsync(bool DeleteShapshots = true, bool bOnAutoDelete = false);
|
SB_STATUS DeleteContentAsync(bool DeleteShapshots = true, bool bOnAutoDelete = false);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -118,6 +123,7 @@ public slots:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class CSbiePlusAPI;
|
friend class CSbiePlusAPI;
|
||||||
|
|
||||||
virtual bool CheckUnsecureConfig() const;
|
virtual bool CheckUnsecureConfig() const;
|
||||||
|
|
||||||
virtual bool TestProgramGroup(const QString& Group, const QString& ProgName);
|
virtual bool TestProgramGroup(const QString& Group, const QString& ProgName);
|
||||||
|
|
|
@ -111,6 +111,7 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent)
|
||||||
m_pMenuContent->addSeparator();
|
m_pMenuContent->addSeparator();
|
||||||
m_pMenuExplore = m_pMenuContent->addAction(CSandMan::GetIcon("Explore"), tr("Explore Content"), this, SLOT(OnSandBoxAction()));
|
m_pMenuExplore = m_pMenuContent->addAction(CSandMan::GetIcon("Explore"), tr("Explore Content"), this, SLOT(OnSandBoxAction()));
|
||||||
m_pMenuRegEdit = m_pMenuContent->addAction(CSandMan::GetIcon("RegEdit"), tr("Open Registry"), this, SLOT(OnSandBoxAction()));
|
m_pMenuRegEdit = m_pMenuContent->addAction(CSandMan::GetIcon("RegEdit"), tr("Open Registry"), this, SLOT(OnSandBoxAction()));
|
||||||
|
m_pMenuRefresh = m_pMenu->addAction(CSandMan::GetIcon("Refresh"), tr("Refresh Info"), this, SLOT(OnSandBoxAction()));
|
||||||
m_pMenuSnapshots = m_pMenu->addAction(CSandMan::GetIcon("Snapshots"), tr("Snapshots Manager"), this, SLOT(OnSandBoxAction()));
|
m_pMenuSnapshots = m_pMenu->addAction(CSandMan::GetIcon("Snapshots"), tr("Snapshots Manager"), this, SLOT(OnSandBoxAction()));
|
||||||
m_pMenuRecover = m_pMenu->addAction(CSandMan::GetIcon("Recover"), tr("Recover Files"), this, SLOT(OnSandBoxAction()));
|
m_pMenuRecover = m_pMenu->addAction(CSandMan::GetIcon("Recover"), tr("Recover Files"), this, SLOT(OnSandBoxAction()));
|
||||||
m_pMenuCleanUp = m_pMenu->addAction(CSandMan::GetIcon("Erase"), tr("Delete Content"), this, SLOT(OnSandBoxAction()));
|
m_pMenuCleanUp = m_pMenu->addAction(CSandMan::GetIcon("Erase"), tr("Delete Content"), this, SLOT(OnSandBoxAction()));
|
||||||
|
@ -134,6 +135,10 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent)
|
||||||
m_pMenuPresetsShares = m_pMenuPresets->addAction(tr("Allow Network Shares"), this, SLOT(OnSandBoxAction()));
|
m_pMenuPresetsShares = m_pMenuPresets->addAction(tr("Allow Network Shares"), this, SLOT(OnSandBoxAction()));
|
||||||
m_pMenuPresetsShares->setCheckable(true);
|
m_pMenuPresetsShares->setCheckable(true);
|
||||||
|
|
||||||
|
m_pMenuPresets->addSeparator();
|
||||||
|
m_pMenuPresetsRecovery = m_pMenuPresets->addAction(tr("Immediate Recovery"), this, SLOT(OnSandBoxAction()));
|
||||||
|
m_pMenuPresetsRecovery->setCheckable(true);
|
||||||
|
|
||||||
m_pMenuDuplicate = m_pMenu->addAction(CSandMan::GetIcon("Duplicate"), tr("Duplicate Sandbox"), this, SLOT(OnSandBoxAction()));
|
m_pMenuDuplicate = m_pMenu->addAction(CSandMan::GetIcon("Duplicate"), tr("Duplicate Sandbox"), this, SLOT(OnSandBoxAction()));
|
||||||
m_pMenuRename = m_pMenu->addAction(CSandMan::GetIcon("Rename"), tr("Rename Sandbox"), this, SLOT(OnSandBoxAction()));
|
m_pMenuRename = m_pMenu->addAction(CSandMan::GetIcon("Rename"), tr("Rename Sandbox"), this, SLOT(OnSandBoxAction()));
|
||||||
m_iMoveTo = m_pMenu->actions().count();
|
m_iMoveTo = m_pMenu->actions().count();
|
||||||
|
@ -197,6 +202,7 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent)
|
||||||
m_pMenu2->addAction(m_pMenuCleanUp);
|
m_pMenu2->addAction(m_pMenuCleanUp);
|
||||||
m_pMenu2->addSeparator();
|
m_pMenu2->addSeparator();
|
||||||
m_pMenu2->addAction(m_pMenuOptions);
|
m_pMenu2->addAction(m_pMenuOptions);
|
||||||
|
m_pMenu2->addMenu(m_pMenuPresets);
|
||||||
|
|
||||||
QByteArray Columns = theConf->GetBlob("MainWindow/BoxTree_Columns");
|
QByteArray Columns = theConf->GetBlob("MainWindow/BoxTree_Columns");
|
||||||
if (Columns.isEmpty())
|
if (Columns.isEmpty())
|
||||||
|
@ -314,8 +320,13 @@ void CSbieView::Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Added.isEmpty()) {
|
if (!Added.isEmpty()) {
|
||||||
foreach(const QVariant &ID, Added)
|
foreach(const QVariant& ID, Added) {
|
||||||
m_Groups[""].append(ID.toString());
|
if (ID.type() == QVariant::String) {
|
||||||
|
QString id = ID.toString();
|
||||||
|
if (id.left(1) == "!") id.remove(0, 1); // remove group group marker "!"
|
||||||
|
m_Groups[""].append(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString Grouping = CSbieView__SerializeGroup(m_Groups);
|
QString Grouping = CSbieView__SerializeGroup(m_Groups);
|
||||||
theAPI->GetUserSettings()->SetText("BoxDisplayOrder", Grouping);
|
theAPI->GetUserSettings()->SetText("BoxDisplayOrder", Grouping);
|
||||||
|
@ -449,6 +460,7 @@ bool CSbieView::UpdateMenu()
|
||||||
m_pMenuPresetsFakeAdmin->setChecked(pBox && pBox->GetBool("DropAdminRights", false) && pBox->GetBool("FakeAdminRights", false));
|
m_pMenuPresetsFakeAdmin->setChecked(pBox && pBox->GetBool("DropAdminRights", false) && pBox->GetBool("FakeAdminRights", false));
|
||||||
m_pMenuPresetsINet->setChecked(pBox && pBox.objectCast<CSandBoxPlus>()->IsINetBlocked());
|
m_pMenuPresetsINet->setChecked(pBox && pBox.objectCast<CSandBoxPlus>()->IsINetBlocked());
|
||||||
m_pMenuPresetsShares->setChecked(pBox && pBox.objectCast<CSandBoxPlus>()->HasSharesAccess());
|
m_pMenuPresetsShares->setChecked(pBox && pBox.objectCast<CSandBoxPlus>()->HasSharesAccess());
|
||||||
|
m_pMenuPresetsRecovery->setChecked(pBox && pBox->GetBool("AutoRecover", false));
|
||||||
|
|
||||||
m_pMenuBrowse->setEnabled(iSandBoxeCount == 1);
|
m_pMenuBrowse->setEnabled(iSandBoxeCount == 1);
|
||||||
m_pMenuExplore->setEnabled(iSandBoxeCount == 1);
|
m_pMenuExplore->setEnabled(iSandBoxeCount == 1);
|
||||||
|
@ -881,6 +893,8 @@ void CSbieView::OnSandBoxAction(QAction* Action)
|
||||||
SandBoxes.first().objectCast<CSandBoxPlus>()->SetINetBlock(m_pMenuPresetsINet->isChecked());
|
SandBoxes.first().objectCast<CSandBoxPlus>()->SetINetBlock(m_pMenuPresetsINet->isChecked());
|
||||||
else if (Action == m_pMenuPresetsShares)
|
else if (Action == m_pMenuPresetsShares)
|
||||||
SandBoxes.first().objectCast<CSandBoxPlus>()->SetAllowShares(m_pMenuPresetsShares->isChecked());
|
SandBoxes.first().objectCast<CSandBoxPlus>()->SetAllowShares(m_pMenuPresetsShares->isChecked());
|
||||||
|
else if (Action == m_pMenuPresetsRecovery)
|
||||||
|
m_pMenuPresetsRecovery->setChecked(SandBoxes.first()->SetBool("AutoRecover", m_pMenuPresetsRecovery->isChecked()));
|
||||||
else if (Action == m_pMenuOptions)
|
else if (Action == m_pMenuOptions)
|
||||||
{
|
{
|
||||||
OnDoubleClicked(m_pSbieTree->selectedRows().first());
|
OnDoubleClicked(m_pSbieTree->selectedRows().first());
|
||||||
|
@ -909,6 +923,13 @@ void CSbieView::OnSandBoxAction(QAction* Action)
|
||||||
SetForegroundWindow((HWND)pFileBrowserWindow->winId());
|
SetForegroundWindow((HWND)pFileBrowserWindow->winId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (Action == m_pMenuRefresh)
|
||||||
|
{
|
||||||
|
foreach(const CSandBoxPtr& pBox, SandBoxes)
|
||||||
|
{
|
||||||
|
pBox.objectCast<CSandBoxPlus>()->UpdateSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (Action == m_pMenuExplore)
|
else if (Action == m_pMenuExplore)
|
||||||
{
|
{
|
||||||
if (SandBoxes.first()->IsEmpty()) {
|
if (SandBoxes.first()->IsEmpty()) {
|
||||||
|
@ -1281,11 +1302,14 @@ void CSbieView::OnDoubleClicked(const QModelIndex& index)
|
||||||
if (pBox.isNull())
|
if (pBox.isNull())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (index.column() == CSbieModel::ePath)
|
if ((QGuiApplication::queryKeyboardModifiers() & Qt::ControlModifier) == 0) {
|
||||||
OnSandBoxAction(m_pMenuExplore);
|
|
||||||
|
|
||||||
if (index.column() != CSbieModel::eName)
|
if (index.column() == CSbieModel::ePath)
|
||||||
return;
|
OnSandBoxAction(m_pMenuExplore);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (index.column() != CSbieModel::eName)
|
||||||
|
// return;
|
||||||
|
|
||||||
if (!pBox->IsEnabled())
|
if (!pBox->IsEnabled())
|
||||||
{
|
{
|
||||||
|
|
|
@ -119,12 +119,14 @@ private:
|
||||||
QAction* m_pMenuPresetsFakeAdmin;
|
QAction* m_pMenuPresetsFakeAdmin;
|
||||||
QAction* m_pMenuPresetsINet;
|
QAction* m_pMenuPresetsINet;
|
||||||
QAction* m_pMenuPresetsShares;
|
QAction* m_pMenuPresetsShares;
|
||||||
|
QAction* m_pMenuPresetsRecovery;
|
||||||
QAction* m_pMenuOptions;
|
QAction* m_pMenuOptions;
|
||||||
QAction* m_pMenuSnapshots;
|
QAction* m_pMenuSnapshots;
|
||||||
QAction* m_pMenuEmptyBox;
|
QAction* m_pMenuEmptyBox;
|
||||||
QMenu* m_pMenuContent;
|
QMenu* m_pMenuContent;
|
||||||
QAction* m_pMenuExplore;
|
QAction* m_pMenuExplore;
|
||||||
QAction* m_pMenuBrowse;
|
QAction* m_pMenuBrowse;
|
||||||
|
QAction* m_pMenuRefresh;
|
||||||
QAction* m_pMenuRegEdit;
|
QAction* m_pMenuRegEdit;
|
||||||
QAction* m_pMenuRecover;
|
QAction* m_pMenuRecover;
|
||||||
QAction* m_pMenuCleanUp;
|
QAction* m_pMenuCleanUp;
|
||||||
|
|
|
@ -223,7 +223,7 @@ void CFileBrowserWindow::OnFileMenu(const QPoint&)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SB_PROGRESS Status = theGUI->RecoverFiles(FileList, 0);
|
SB_PROGRESS Status = theGUI->RecoverFiles(m_pBox->GetName(), FileList, 0);
|
||||||
if (Status.GetStatus() == OP_ASYNC)
|
if (Status.GetStatus() == OP_ASYNC)
|
||||||
theGUI->AddAsyncOp(Status.GetValue());
|
theGUI->AddAsyncOp(Status.GetValue());
|
||||||
|
|
||||||
|
|
|
@ -799,6 +799,16 @@ void COptionsWindow::SaveIniSection()
|
||||||
LoadIniSection();
|
LoadIniSection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "OptionsAccess.cpp"
|
||||||
|
#include "OptionsAdvanced.cpp"
|
||||||
|
#include "OptionsForce.cpp"
|
||||||
|
#include "OptionsGeneral.cpp"
|
||||||
|
#include "OptionsGrouping.cpp"
|
||||||
|
#include "OptionsNetwork.cpp"
|
||||||
|
#include "OptionsRecovery.cpp"
|
||||||
|
#include "OptionsStart.cpp"
|
||||||
|
#include "OptionsStop.cpp"
|
||||||
|
#include "OptionsTemplates.cpp"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
|
@ -380,7 +380,7 @@ void CPopUpWindow::OnRecoverFile(int Action)
|
||||||
QList<QPair<QString, QString>> FileList;
|
QList<QPair<QString, QString>> FileList;
|
||||||
FileList.append(qMakePair(pEntry->m_BoxPath, RecoveryFolder + "\\" + FileName));
|
FileList.append(qMakePair(pEntry->m_BoxPath, RecoveryFolder + "\\" + FileName));
|
||||||
|
|
||||||
SB_PROGRESS Status = theGUI->RecoverFiles(FileList, Action);
|
SB_PROGRESS Status = theGUI->RecoverFiles(pEntry->m_BoxName, FileList, Action);
|
||||||
if (Status.GetStatus() == OP_ASYNC)
|
if (Status.GetStatus() == OP_ASYNC)
|
||||||
theGUI->AddAsyncOp(Status.GetValue());
|
theGUI->AddAsyncOp(Status.GetValue());
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,11 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
CRecoveryWindow::CRecoveryWindow(const CSandBoxPtr& pBox, QWidget *parent)
|
CRecoveryWindow::CRecoveryWindow(const CSandBoxPtr& pBox, bool bImmediate, QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
|
m_bImmediate = bImmediate;
|
||||||
|
|
||||||
Qt::WindowFlags flags = windowFlags();
|
Qt::WindowFlags flags = windowFlags();
|
||||||
flags |= Qt::CustomizeWindowHint;
|
flags |= Qt::CustomizeWindowHint;
|
||||||
//flags &= ~Qt::WindowContextHelpButtonHint;
|
//flags &= ~Qt::WindowContextHelpButtonHint;
|
||||||
|
@ -28,7 +30,7 @@ CRecoveryWindow::CRecoveryWindow(const CSandBoxPtr& pBox, QWidget *parent)
|
||||||
//setWindowState(Qt::WindowActive);
|
//setWindowState(Qt::WindowActive);
|
||||||
SetForegroundWindow((HWND)QWidget::winId());
|
SetForegroundWindow((HWND)QWidget::winId());
|
||||||
|
|
||||||
bool bAlwaysOnTop = theConf->GetBool("Options/AlwaysOnTop", false);
|
bool bAlwaysOnTop = theConf->GetBool("Options/AlwaysOnTop", false) || (bImmediate && theConf->GetBool("Options/RecoveryOnTop", true));
|
||||||
this->setWindowFlag(Qt::WindowStaysOnTopHint, bAlwaysOnTop);
|
this->setWindowFlag(Qt::WindowStaysOnTopHint, bAlwaysOnTop);
|
||||||
|
|
||||||
if (!bAlwaysOnTop) {
|
if (!bAlwaysOnTop) {
|
||||||
|
@ -302,6 +304,9 @@ int CRecoveryWindow::FindFiles()
|
||||||
Count += FindFiles(Folder);
|
Count += FindFiles(Folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_bImmediate && m_FileMap.isEmpty())
|
||||||
|
this->close();
|
||||||
|
|
||||||
m_pFileModel->Sync(m_FileMap);
|
m_pFileModel->Sync(m_FileMap);
|
||||||
ui.treeFiles->expandAll();
|
ui.treeFiles->expandAll();
|
||||||
return Count;
|
return Count;
|
||||||
|
@ -481,7 +486,7 @@ void CRecoveryWindow::RecoverFiles(bool bBrowse, QString RecoveryFolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SB_PROGRESS Status = theGUI->RecoverFiles(FileList);
|
SB_PROGRESS Status = theGUI->RecoverFiles(m_pBox->GetName(), FileList);
|
||||||
if (Status.GetStatus() == OP_ASYNC)
|
if (Status.GetStatus() == OP_ASYNC)
|
||||||
{
|
{
|
||||||
connect(Status.GetValue().data(), SIGNAL(Finished()), this, SLOT(FindFiles()));
|
connect(Status.GetValue().data(), SIGNAL(Finished()), this, SLOT(FindFiles()));
|
||||||
|
@ -504,6 +509,7 @@ void CRecoveryWindow::OnCloseUntil()
|
||||||
|
|
||||||
void CRecoveryWindow::OnAutoDisable()
|
void CRecoveryWindow::OnAutoDisable()
|
||||||
{
|
{
|
||||||
|
m_pBox.objectCast<CSandBoxPlus>()->SetSuspendRecovery();
|
||||||
m_pBox->SetBool("AutoRecover", false);
|
m_pBox->SetBool("AutoRecover", false);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ class CRecoveryWindow : public QDialog
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CRecoveryWindow(const CSandBoxPtr& pBox, QWidget *parent = Q_NULLPTR);
|
CRecoveryWindow(const CSandBoxPtr& pBox, bool bImmediate = false, QWidget *parent = Q_NULLPTR);
|
||||||
~CRecoveryWindow();
|
~CRecoveryWindow();
|
||||||
|
|
||||||
bool IsDeleteShapshots() { return m_DeleteShapshots; }
|
bool IsDeleteShapshots() { return m_DeleteShapshots; }
|
||||||
|
@ -85,6 +85,7 @@ protected:
|
||||||
bool m_bTargetsChanged;
|
bool m_bTargetsChanged;
|
||||||
bool m_bReloadPending;
|
bool m_bReloadPending;
|
||||||
bool m_DeleteShapshots;
|
bool m_DeleteShapshots;
|
||||||
|
bool m_bImmediate;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::RecoveryWindow ui;
|
Ui::RecoveryWindow ui;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue