This commit is contained in:
DavidXanatos 2023-07-23 14:46:24 +02:00
parent 0d7034ce7e
commit 3372b74a22
13 changed files with 436 additions and 48 deletions

View File

@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Changed
- reworked Nt Object Handle handling
- "OpenClipboard=n" now is also implemented in user mode, making it work for green boxes
- changed Delete V2 scheme to use drive letters in FilePaths.dat (remains backwards compatible with using NT Paths) [#3053](https://github.com/sandboxie-plus/Sandboxie/issues/3053)
### Fixed
- fixed "Disable Security Isolation" causes a game to stop playing audio [#2893](https://github.com/sandboxie-plus/Sandboxie/issues/2893)
@ -31,6 +32,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- fixed crash issue with not peroeprly termianted script engine [#3120](https://github.com/sandboxie-plus/Sandboxie/issues/3120)
- fixed ImDisk under Sandboxie supervision causes SBIE2337 and sometimes BSoD [#1092)(https://github.com/sandboxie-plus/Sandboxie/issues/1092)
- fixed Snapshots don't merge duplicate directory junctions [#3016](https://github.com/sandboxie-plus/Sandboxie/issues/3016)
- fixed Snapshot related issue when using Delete V2 rename functionality
- fixed issue with Delete V2 when using network shares
- fixed issue when using "UseVolumeSerialNumbers=y" with accessing drive roots
- fixed Remove-Snapshot resurrects deleted files when using Delete V2 [#3015](https://github.com/sandboxie-plus/Sandboxie/issues/3015)

View File

@ -48,9 +48,10 @@ extern __declspec(dllexport) int __CRTDECL Sbie_snprintf(char *_Buffer, size_t C
#define TRUE_NAME_BUFFER 0
#define COPY_NAME_BUFFER 1
#define TMPL_NAME_BUFFER 2
#define MISC_NAME_BUFFER 3 // 4, 5, 6, 7
#define NAME_BUFFER_COUNT 8
#define NAME_BUFFER_DEPTH 16 // 12
#define NORM_NAME_BUFFER 3
#define MISC_NAME_BUFFER 4 // 5 - 11
#define NAME_BUFFER_COUNT 12
#define NAME_BUFFER_DEPTH 16
#ifdef _WIN64

View File

@ -338,7 +338,7 @@ ALIGNED WCHAR *Dll_GetTlsNameBuffer(THREAD_DATA *data, ULONG which, ULONG size)
DbgTrace("Dll_GetTlsNameBuffer, %s, %d\r\n", func, which);
#endif
if (which >= NAME_BUFFER_COUNT - 4)
if (which >= NAME_BUFFER_COUNT - 2)
SbieApi_Log(2310, L"%d", which);
if (which >= NAME_BUFFER_COUNT) {
ExitProcess(-1);

View File

@ -873,8 +873,8 @@ check_sandbox_prefix:
// skip any suffix after the drive letter
if (File_DriveAddSN) {
WCHAR* ptr = wcschr(*OutTruePath + _DriveLen + 1, L'\\');
if (ptr)
len = (ULONG)(ptr - *OutTruePath);
if (!ptr) ptr = wcschr(*OutTruePath + _DriveLen + 1, L'\0');
len = (ULONG)(ptr - *OutTruePath);
}
File_GetName_FixTruePrefix(TlsData,
@ -1259,8 +1259,8 @@ check_sandbox_prefix:
*name = drive_letter;
++name;
if (File_DriveAddSN && *drive->sn)
{
if (File_DriveAddSN && *drive->sn) {
*name = L'~';
++name;
wcscpy(name, drive->sn);
@ -2538,7 +2538,8 @@ _FX NTSTATUS File_NtCreateFileImpl(
// SbieDrv has removed privileges
//
CreateOptions &= ~FILE_OPEN_FOR_BACKUP_INTENT;
if (!Dll_CompartmentMode)
CreateOptions &= ~FILE_OPEN_FOR_BACKUP_INTENT;
//
// get the full paths for the true and copy files.
@ -2916,8 +2917,7 @@ ReparseLoop:
}
}
else if (status == STATUS_OBJECT_NAME_NOT_FOUND ||
status == STATUS_OBJECT_PATH_NOT_FOUND) {
else if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND) {
//
// the CopyPath file does not exist, but its parent path may exist
@ -2969,7 +2969,7 @@ ReparseLoop:
// When using Rule specificity we need to create some dummy directories
//
File_CreateBoxedPath(TruePath);
File_CreateBoxedPath(OriginalPath ? OriginalPath : TruePath);
}
else if (OriginalPath) {

View File

@ -314,6 +314,71 @@ _FX ULONG File_GetPathFlags_internal(LIST* Root, const WCHAR* Path, WCHAR** pRel
}
//---------------------------------------------------------------------------
// File_NormalizePath
//---------------------------------------------------------------------------
_FX const WCHAR* File_NormalizePath(const WCHAR* path, int slot)
{
//
// if we have a path that looks like any of these
// \Device\LanmanRedirector\server\shr\f1.txt
// \Device\LanmanRedirector\;Q:000000000000b09f\server\shr\f1.txt
// \Device\Mup\;LanmanRedirector\server\share\f1.txt
// \Device\Mup\;LanmanRedirector\;Q:000000000000b09f\server\share\f1.txt
// then translate to
// \Device\Mup\server\shr\f1.txt
// and test again. We do this because open/closed paths are
// recorded in the \Device\Mup format. See File_TranslateShares.
//
ULONG PrefixLen;
if (_wcsnicmp(path, File_Redirector, File_RedirectorLen - 1) == 0)
PrefixLen = File_RedirectorLen - 1;
else if (_wcsnicmp(path, File_MupRedir, File_MupRedirLen - 1) == 0)
PrefixLen = File_MupRedirLen - 1;
else if (_wcsnicmp(path, File_DfsClientRedir, File_DfsClientRedirLen - 1) == 0)
PrefixLen = File_DfsClientRedirLen - 1;
else if (_wcsnicmp(path, File_HgfsRedir, File_HgfsRedirLen - 1) == 0)
PrefixLen = File_HgfsRedirLen - 1;
else if (_wcsnicmp(path, File_Mup, File_MupLen - 1) == 0)
PrefixLen = File_MupLen - 1;
else
PrefixLen = 0;
if (PrefixLen && path[PrefixLen] == L'\\' &&
path[PrefixLen + 1] != L'\0') {
const WCHAR* ptr = path + PrefixLen;
if (ptr[1] == L';')
ptr = wcschr(ptr + 2, L'\\');
if (ptr && ptr[0] && ptr[1]) {
//
// the path represents a network share
//
THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
ULONG len1 = wcslen(ptr + 1);
ULONG len2 = (File_MupLen + len1 + 8) * sizeof(WCHAR);
WCHAR* path2 = Dll_GetTlsNameBuffer(TlsData, slot, len2);
wmemcpy(path2, File_Mup, File_MupLen);
path2[File_MupLen] = L'\\';
wmemcpy(path2 + File_MupLen + 1, ptr + 1, len1 + 1);
len1 += File_MupLen + 1;
return path2;
}
}
return path;
}
//---------------------------------------------------------------------------
// File_GetPathFlags
//---------------------------------------------------------------------------
@ -327,7 +392,7 @@ _FX ULONG File_GetPathFlags(const WCHAR* Path, WCHAR** pRelocation)
EnterCriticalSection(File_PathRoot_CritSec);
Flags = File_GetPathFlags_internal(&File_PathRoot, Path, pRelocation, TRUE);
Flags = File_GetPathFlags_internal(&File_PathRoot, File_NormalizePath(Path, NORM_NAME_BUFFER), pRelocation, TRUE);
LeaveCriticalSection(File_PathRoot_CritSec);
@ -340,7 +405,7 @@ _FX ULONG File_GetPathFlags(const WCHAR* Path, WCHAR** pRelocation)
//---------------------------------------------------------------------------
_FX VOID File_SavePathNode_internal(HANDLE hPathsFile, LIST* parent, WCHAR* Path, ULONG Length, ULONG SetFlags)
_FX VOID File_SavePathNode_internal(HANDLE hPathsFile, LIST* parent, WCHAR* Path, ULONG Length, ULONG SetFlags, WCHAR* (*TranslatePath)(const WCHAR *))
{
IO_STATUS_BLOCK IoStatusBlock;
@ -369,7 +434,9 @@ _FX VOID File_SavePathNode_internal(HANDLE hPathsFile, LIST* parent, WCHAR* Path
if ((child->flags & ~SetFlags) != 0 || child->relocation != NULL) {
// write the path
NtWriteFile(hPathsFile, NULL, NULL, NULL, &IoStatusBlock, Path, Path_Len * sizeof(WCHAR), NULL, NULL);
WCHAR* PathEx = TranslatePath ? TranslatePath(Path) : NULL;
NtWriteFile(hPathsFile, NULL, NULL, NULL, &IoStatusBlock, PathEx ? PathEx : Path, wcslen(PathEx ? PathEx : Path) * sizeof(WCHAR), NULL, NULL);
if (PathEx) Dll_Free(PathEx);
// write the flags
_ultow(child->flags, FlagStr + 1, 16);
@ -377,15 +444,19 @@ _FX VOID File_SavePathNode_internal(HANDLE hPathsFile, LIST* parent, WCHAR* Path
// write the relocation
if (child->relocation != NULL) {
NtWriteFile(hPathsFile, NULL, NULL, NULL, &IoStatusBlock, FlagStr, sizeof(WCHAR), NULL, NULL); // write |
NtWriteFile(hPathsFile, NULL, NULL, NULL, &IoStatusBlock, child->relocation, wcslen(child->relocation) * sizeof(WCHAR), NULL, NULL);
WCHAR* RelocationEx = TranslatePath ? TranslatePath(child->relocation) : NULL;
NtWriteFile(hPathsFile, NULL, NULL, NULL, &IoStatusBlock, RelocationEx ? RelocationEx : child->relocation, wcslen(RelocationEx ? RelocationEx : child->relocation) * sizeof(WCHAR), NULL, NULL);
if (RelocationEx) Dll_Free(RelocationEx);
}
// write line ending
NtWriteFile(hPathsFile, NULL, NULL, NULL, &IoStatusBlock, (void*)CrLf, sizeof(CrLf) - sizeof(WCHAR), NULL, NULL);
}
File_SavePathNode_internal(hPathsFile, &child->items, Path, Path_Len, SetFlags | child->flags);
File_SavePathNode_internal(hPathsFile, &child->items, Path, Path_Len, SetFlags | child->flags, TranslatePath);
child = List_Next(child);
}
@ -397,7 +468,7 @@ _FX VOID File_SavePathNode_internal(HANDLE hPathsFile, LIST* parent, WCHAR* Path
//---------------------------------------------------------------------------
_FX VOID File_SavePathTree_internal(LIST* Root, const WCHAR* name)
_FX VOID File_SavePathTree_internal(LIST* Root, const WCHAR* name, WCHAR* (*TranslatePath)(const WCHAR *))
{
WCHAR PathsFile[MAX_PATH] = { 0 };
wcscpy(PathsFile, Dll_BoxFilePath);
@ -417,7 +488,7 @@ _FX VOID File_SavePathTree_internal(LIST* Root, const WCHAR* name)
WCHAR* Path = (WCHAR *)Dll_Alloc((0x7FFF + 1)*sizeof(WCHAR)); // max nt path
File_SavePathNode_internal(hPathsFile, Root, Path, 0, 0);
File_SavePathNode_internal(hPathsFile, Root, Path, 0, 0, TranslatePath);
Dll_Free(Path);
@ -425,6 +496,84 @@ _FX VOID File_SavePathTree_internal(LIST* Root, const WCHAR* name)
}
//---------------------------------------------------------------------------
// File_TranslateNtToDosPath2
//---------------------------------------------------------------------------
_FX WCHAR* File_TranslateNtToDosPath2(const WCHAR *NtPath)
{
WCHAR *DosPath = NULL;
ULONG len_nt;
len_nt = wcslen(NtPath) + 11;
DosPath = Dll_Alloc(len_nt * sizeof(WCHAR));
wcscpy(DosPath, NtPath);
//
// Hack Hack: when we load a drive which does not exist we create an entry like
// L"\\C:\\path" in out tree to not forget it even though the NtPath is unknown
// here we must handle that special case and strip the L'\\'
//
const WCHAR* backslash = wcschr(DosPath+1, L'\\');
if (!backslash) backslash = wcschr(DosPath, L'\0');
if (*(backslash - 1) == L':') {
wmemmove(DosPath, DosPath + 1, wcslen(DosPath)); // -1 (for '\\') + 1 (for '\0')
return DosPath;
}
if (_wcsnicmp(DosPath, File_Mup, File_MupLen) == 0) {
WCHAR *ptr = DosPath + File_MupLen - 1;
wmemmove(DosPath + 1, ptr, wcslen(ptr) + 1);
} else {
const FILE_DRIVE *drive;
ULONG path_len, prefix_len;
path_len = wcslen(DosPath);
drive = File_GetDriveForPath(DosPath, path_len);
if (drive)
prefix_len = drive->len;
else
drive = File_GetDriveForUncPath(DosPath, path_len, &prefix_len);
if (drive) {
WCHAR drive_letter = drive->letter;
WCHAR *ptr = DosPath + prefix_len;
LeaveCriticalSection(File_DrivesAndLinks_CritSec);
if (*ptr == L'\\' || *ptr == L'\0') {
path_len = wcslen(ptr);
wmemmove(DosPath + 2, ptr, path_len + 1);
DosPath[0] = drive_letter;
DosPath[1] = L':';
if (File_DriveAddSN && *drive->sn) {
wmemmove(DosPath + 11, DosPath + 1, path_len + 2);
DosPath[1] = L'~';
wmemcpy(DosPath + 2, drive->sn, 9);
}
}
} else {
Dll_Free(DosPath);
DosPath = NULL;
}
}
return DosPath;
}
//---------------------------------------------------------------------------
// File_SavePathTree
//---------------------------------------------------------------------------
@ -434,7 +583,7 @@ _FX BOOLEAN File_SavePathTree()
{
EnterCriticalSection(File_PathRoot_CritSec);
File_SavePathTree_internal(&File_PathRoot, FILE_PATH_FILE_NAME);
File_SavePathTree_internal(&File_PathRoot, FILE_PATH_FILE_NAME, File_TranslateNtToDosPath2);
File_GetAttributes_internal(FILE_PATH_FILE_NAME, &File_PathsFileSize, &File_PathsFileDate, NULL);
@ -482,7 +631,7 @@ _FX void File_ReleaseMutex(HANDLE hMutex)
//---------------------------------------------------------------------------
_FX BOOLEAN File_LoadPathTree_internal(LIST* Root, const WCHAR* name)
_FX BOOLEAN File_LoadPathTree_internal(LIST* Root, const WCHAR* name, WCHAR* (*TranslatePath)(const WCHAR *))
{
WCHAR PathsFile[MAX_PATH] = { 0 };
wcscpy(PathsFile, Dll_BoxFilePath);
@ -529,16 +678,26 @@ _FX BOOLEAN File_LoadPathTree_internal(LIST* Root, const WCHAR* name)
WCHAR savechar = Line[LineLen];
Line[LineLen] = L'\0';
WCHAR* Path = Line;
WCHAR* Sep = wcschr(Line, L'|');
if (!Sep || Sep > Next) continue; // invalid line, flags field missing
*Sep = L'\0';
WCHAR* Relocation = NULL;
WCHAR* endptr;
ULONG Flags = wcstoul(Sep + 1, &endptr, 16);
if (endptr && *endptr == L'|') endptr++;
else endptr = NULL;
if (endptr && *endptr == L'|')
Relocation = endptr + 1;
File_SetPathFlags_internal(Root, Line, Flags, 0, endptr);
WCHAR* PathEx = TranslatePath ? TranslatePath(Path) : NULL;
WCHAR* RelocationEx = TranslatePath ? TranslatePath(Relocation) : NULL;
File_SetPathFlags_internal(Root, PathEx ? PathEx : Path, Flags, 0, RelocationEx ? RelocationEx : Relocation);
if (PathEx) Dll_Free(PathEx);
if (RelocationEx) Dll_Free(RelocationEx);
*Sep = L'|';
Line[LineLen] = savechar;
@ -552,6 +711,73 @@ _FX BOOLEAN File_LoadPathTree_internal(LIST* Root, const WCHAR* name)
}
//---------------------------------------------------------------------------
// File_TranslateDosToNtPath2
//---------------------------------------------------------------------------
_FX WCHAR *File_TranslateDosToNtPath2(const WCHAR *DosPath)
{
WCHAR *NtPath = NULL;
ULONG len_dos;
if (DosPath && DosPath[0] && DosPath[1]) {
if (DosPath[0] == L'\\' && DosPath[1] == L'\\') {
//
// network path
//
DosPath += 2;
len_dos = wcslen(DosPath) + 1;
NtPath = Dll_Alloc((File_MupLen + len_dos) * sizeof(WCHAR));
wmemcpy(NtPath, File_Mup, File_MupLen);
wmemcpy(NtPath + File_MupLen, DosPath, len_dos);
} else if (DosPath[0] != L'\\') {
const WCHAR* backslash = wcschr(DosPath, L'\\');
if(!backslash) backslash = wcschr(DosPath, L'\0');
if (*(backslash - 1) == L':') {
ULONG path_pos = (ULONG)(backslash - DosPath);
//
// drive-letter path
//
FILE_DRIVE* drive = File_GetDriveForLetter(DosPath[0]);
if (drive) {
if (File_DriveAddSN && *drive->sn) {
//
// if the volume serial numbers dont match return NULL
//
if (_wcsnicmp(DosPath + 2, drive->sn, 9) != 0) {
LeaveCriticalSection(File_DrivesAndLinks_CritSec);
return NULL;
}
}
DosPath += path_pos;
len_dos = wcslen(DosPath) + 1;
NtPath = Dll_Alloc((drive->len + len_dos) * sizeof(WCHAR));
wmemcpy(NtPath, drive->path, drive->len);
wmemcpy(NtPath + drive->len, DosPath, len_dos);
LeaveCriticalSection(File_DrivesAndLinks_CritSec);
}
}
}
}
return NtPath;
}
//---------------------------------------------------------------------------
// File_LoadPathTree
//---------------------------------------------------------------------------
@ -563,7 +789,7 @@ _FX BOOLEAN File_LoadPathTree()
EnterCriticalSection(File_PathRoot_CritSec);
File_LoadPathTree_internal(&File_PathRoot, FILE_PATH_FILE_NAME);
File_LoadPathTree_internal(&File_PathRoot, FILE_PATH_FILE_NAME, File_TranslateDosToNtPath2);
LeaveCriticalSection(File_PathRoot_CritSec);
@ -738,7 +964,7 @@ _FX NTSTATUS File_MarkDeleted_v2(const WCHAR* TruePath)
EnterCriticalSection(File_PathRoot_CritSec);
BOOLEAN bSet = File_MarkDeleted_internal(&File_PathRoot, TruePath);
BOOLEAN bSet = File_MarkDeleted_internal(&File_PathRoot, File_NormalizePath(TruePath, NORM_NAME_BUFFER));
LeaveCriticalSection(File_PathRoot_CritSec);
@ -876,7 +1102,7 @@ _FX NTSTATUS File_SetRelocation(const WCHAR* OldTruePath, const WCHAR* NewTruePa
EnterCriticalSection(File_PathRoot_CritSec);
File_SetRelocation_internal(&File_PathRoot, OldTruePath, NewTruePath);
File_SetRelocation_internal(&File_PathRoot, File_NormalizePath(OldTruePath, NORM_NAME_BUFFER), File_NormalizePath(NewTruePath, MISC_NAME_BUFFER));
LeaveCriticalSection(File_PathRoot_CritSec);

View File

@ -617,8 +617,21 @@ _FX NTSTATUS File_OpenForMerge(
if (FILE_PATH_DELETED(TruePathFlags))
TruePathDeleted = TRUE;
else if (OldTruePath) {
OriginalPath = TruePath;
TruePath = OldTruePath;
if (File_Snapshot != NULL) {
//
// note: File_ResolveTruePath returns a buffer from the TMPL_NAME_BUFFER slot,
// which is reused byFile_MakeSnapshotPath, so we need to make non reusable copy
//
TruePath = Dll_GetTlsNameBuffer(TlsData, MISC_NAME_BUFFER, (wcslen(OldTruePath) + 1) * sizeof(WCHAR));
wcscpy(TruePath, OldTruePath);
}
else
TruePath = OldTruePath;
}
}
else {
@ -1535,7 +1548,7 @@ _FX NTSTATUS File_MergeDummy(
}
if (cmp != 0) { // skip duplicates
if (ins_point)
List_Insert_Before(cache_list, ins_point, cache_file);
else

View File

@ -278,7 +278,7 @@ _FX ULONG File_GetPathFlagsEx(const WCHAR *TruePath, const WCHAR *CopyPath, WCHA
// check true path relocation and deletion for the active state
//
Flags = File_GetPathFlags_internal(&File_PathRoot, TruePath, &Relocation, TRUE); // this requires a name buffer
Flags = File_GetPathFlags_internal(&File_PathRoot, File_NormalizePath(TruePath, NORM_NAME_BUFFER), &Relocation, TRUE); // this requires a name buffer
if (FILE_PATH_DELETED(Flags))
goto finish;
}
@ -373,7 +373,7 @@ _FX ULONG File_GetPathFlagsEx(const WCHAR *TruePath, const WCHAR *CopyPath, WCHA
//
TmplRelocation = NULL;
Flags = File_GetPathFlags_internal(&Cur_Snapshot->PathRoot, TruePath, &TmplRelocation, TRUE);
Flags = File_GetPathFlags_internal(&Cur_Snapshot->PathRoot, File_NormalizePath(TruePath, NORM_NAME_BUFFER), &TmplRelocation, TRUE);
if(TmplRelocation)
Relocation = TmplRelocation;
if (FILE_PATH_DELETED(Flags))
@ -477,7 +477,7 @@ _FX void File_InitSnapshots(void)
wcscat(PathFile, L"\\");
wcscat(PathFile, FILE_PATH_FILE_NAME);
File_LoadPathTree_internal(&Cur_Snapshot->PathRoot, PathFile);
File_LoadPathTree_internal(&Cur_Snapshot->PathRoot, PathFile, File_TranslateDosToNtPath);
}
//WCHAR SnapshotName[BOXNAME_COUNT] = { 0 };

View File

@ -80,11 +80,10 @@ static ULONG Key_IsDeletedEx_v2(const WCHAR* TruePath, const WCHAR* ValueName, B
//
VOID File_ClearPathBranche_internal(LIST* parent);
VOID File_SavePathTree_internal(LIST* Root, const WCHAR* name);
BOOLEAN File_LoadPathTree_internal(LIST* Root, const WCHAR* name);
VOID File_SavePathTree_internal(LIST* Root, const WCHAR* name, WCHAR* (*TranslatePath)(const WCHAR *));
BOOLEAN File_LoadPathTree_internal(LIST* Root, const WCHAR* name, WCHAR* (*TranslatePath)(const WCHAR *));
VOID File_SetPathFlags_internal(LIST* Root, const WCHAR* Path, ULONG setFlags, ULONG clrFlags, const WCHAR* Relocation);
ULONG File_GetPathFlags_internal(LIST* Root, const WCHAR* Path, WCHAR** pRelocation, BOOLEAN CheckChildren);
VOID File_SavePathNode_internal(HANDLE hPathsFile, LIST* parent, WCHAR* Path, ULONG Length, ULONG SetFlags);
BOOLEAN File_MarkDeleted_internal(LIST* Root, const WCHAR* Path);
VOID File_SetRelocation_internal(LIST* Root, const WCHAR* OldTruePath, const WCHAR* NewTruePath);
@ -128,7 +127,7 @@ _FX BOOLEAN Key_SavePathTree()
{
EnterCriticalSection(Key_PathRoot_CritSec);
File_SavePathTree_internal(&Key_PathRoot, KEY_PATH_FILE_NAME);
File_SavePathTree_internal(&Key_PathRoot, KEY_PATH_FILE_NAME, NULL);
File_GetAttributes_internal(KEY_PATH_FILE_NAME, &Key_PathsFileSize, &Key_PathsFileDate, NULL);
@ -151,7 +150,7 @@ _FX BOOLEAN Key_LoadPathTree()
EnterCriticalSection(Key_PathRoot_CritSec);
Key_RegPaths_Loaded = File_LoadPathTree_internal(&Key_PathRoot, KEY_PATH_FILE_NAME);
Key_RegPaths_Loaded = File_LoadPathTree_internal(&Key_PathRoot, KEY_PATH_FILE_NAME, NULL);
LeaveCriticalSection(Key_PathRoot_CritSec);

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include <QAbstractEventDispatcher>
#include <QSettings>
#include <ntstatus.h>
#define WIN32_NO_STATUS
@ -348,6 +349,28 @@ CSymbolProvider* CSymbolProvider::Instance()
if (MyBeginInitOnce(InitOnce))
{
/*#ifdef _WIN64
QSettings settings("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows Kits\\Installed Roots", QSettings::NativeFormat);
#else
QSettings settings("HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\Microsoft\\Windows Kits\\Installed Roots", QSettings::NativeFormat);
#endif
QString KitsRoot = settings.value("KitsRoot10").toString(); // Windows 10 SDK
if(KitsRoot.isEmpty())
KitsRoot = settings.value("KitsRoot81").toString(); // Windows 8.1 SDK
if(KitsRoot.isEmpty())
KitsRoot = settings.value("KitsRoot").toString(); // Windows 8 SDK
#if defined(_M_AMD64)
KitsRoot.append("\\Debuggers\\x64\\");
#elif defined(_M_ARM64)
KitsRoot.append("\\Debuggers\\arm64\\");
#else
KitsRoot.append("\\Debuggers\\x86\\");
#endif
HMODULE DbgCoreMod = LoadLibrary((KitsRoot + "dbgcore.dll").toStdWString().c_str());
HMODULE DbgHelpMod = LoadLibrary((KitsRoot + "dbghelp.dll").toStdWString().c_str());
HMODULE SymSrvMod = LoadLibrary((KitsRoot + "symsrv.dll").toStdWString().c_str());*/
HMODULE DbgHelpMod = LoadLibrary(L"dbghelp.dll");
__sys_SymFromAddr = (P_SymFromAddr)GetProcAddress(DbgHelpMod, "SymFromAddr");

View File

@ -100,7 +100,7 @@ NTSTATUS NtIo_RemoveJunction(POBJECT_ATTRIBUTES objattrs)
NTSTATUS NtIo_DeleteFolderRecursivelyImpl(POBJECT_ATTRIBUTES objattrs, bool (*cb)(const WCHAR* info, void* param), void* param);
NTSTATUS NtIo_DeleteFileImpl(ULONG FileAttributes, OBJECT_ATTRIBUTES* attr, bool (*cb)(const WCHAR* info, void* param), void* param)
NTSTATUS NtIo_DeleteFile(ULONG FileAttributes, OBJECT_ATTRIBUTES* attr, bool (*cb)(const WCHAR* info, void* param), void* param)
{
NTSTATUS status;
@ -115,15 +115,18 @@ NTSTATUS NtIo_DeleteFileImpl(ULONG FileAttributes, OBJECT_ATTRIBUTES* attr, bool
if (NT_SUCCESS(status))
status = NtDeleteFile(attr);
if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND)
status = STATUS_SUCCESS; // we wanted it gone and its not here, success
return status;
}
NTSTATUS NtIo_DeleteFileImpl(SNtObject& ntObject, bool (*cb)(const WCHAR* info, void* param), void* param)
NTSTATUS NtIo_DeleteFile(SNtObject& ntObject, bool (*cb)(const WCHAR* info, void* param), void* param)
{
FILE_BASIC_INFORMATION info = { 0 };
NtQueryAttributesFile(&ntObject.attr, &info);
return NtIo_DeleteFileImpl(info.FileAttributes, &ntObject.attr, cb, param);
return NtIo_DeleteFile(info.FileAttributes, &ntObject.attr, cb, param);
}
NTSTATUS NtIo_DeleteFolderRecursivelyImpl(POBJECT_ATTRIBUTES objattrs, bool (*cb)(const WCHAR* info, void* param), void* param)
@ -175,7 +178,7 @@ NTSTATUS NtIo_DeleteFolderRecursivelyImpl(POBJECT_ATTRIBUTES objattrs, bool (*cb
SNtObject ntFoundObject(FileName, Handle);
status = NtIo_DeleteFileImpl(FileAttributes, &ntFoundObject.attr, cb, param);
status = NtIo_DeleteFile(FileAttributes, &ntFoundObject.attr, cb, param);
}
NtClose(Handle);
@ -194,6 +197,9 @@ NTSTATUS NtIo_DeleteFolderRecursively(POBJECT_ATTRIBUTES objattrs, bool (*cb)(co
status = NtDeleteFile(objattrs);
}
if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND)
status = STATUS_SUCCESS; // we wanted it gone and its not here, success
return status;
}
@ -346,7 +352,7 @@ NTSTATUS NtIo_MergeFolder(POBJECT_ATTRIBUTES src_objattrs, POBJECT_ATTRIBUTES de
if (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
if (TargetExists)
status = NtIo_DeleteFileImpl(ntDestObject, cb, param);
status = NtIo_DeleteFile(ntDestObject, cb, param);
if (NT_SUCCESS(status))
status = NtIo_RenameJunction(&ntSrcObject.attr, dest_objattrs, FileName.c_str());
}
@ -360,7 +366,7 @@ NTSTATUS NtIo_MergeFolder(POBJECT_ATTRIBUTES src_objattrs, POBJECT_ATTRIBUTES de
else
{
if (TargetExists)
status = NtIo_DeleteFileImpl(ntDestObject, cb, param);
status = NtIo_DeleteFile(ntDestObject, cb, param);
if (NT_SUCCESS(status))
status = NtIo_RenameFile(&ntSrcObject.attr, dest_objattrs, FileName.c_str());
}

View File

@ -23,10 +23,13 @@ private:
bool NtIo_WaitForFolder(POBJECT_ATTRIBUTES objattrs, int seconds = 10, bool (*cb)(const WCHAR* info, void* param) = NULL, void* param = NULL);
BOOLEAN NtIo_FileExists(POBJECT_ATTRIBUTES objattrs);
NTSTATUS NtIo_RemoveProblematicAttributes(POBJECT_ATTRIBUTES objattrs);
NTSTATUS NtIo_RemoveJunction(POBJECT_ATTRIBUTES objattrs);
NTSTATUS NtIo_DeleteFile(SNtObject& ntObject, bool (*cb)(const WCHAR* info, void* param) = NULL, void* param = NULL);
NTSTATUS NtIo_DeleteFolderRecursively(POBJECT_ATTRIBUTES objattrs, bool (*cb)(const WCHAR* info, void* param) = NULL, void* param = NULL);
NTSTATUS NtIo_RenameFile(POBJECT_ATTRIBUTES src_objattrs, POBJECT_ATTRIBUTES dest_objattrs, const WCHAR* DestName);

View File

@ -471,7 +471,7 @@ SB_PROGRESS CSandBox::RemoveSnapshot(const QString& ID)
CSbieProgressPtr pProgress = CSbieProgressPtr(new CSbieProgress());
if (ChildIDs.count() == 1 || IsCurrent)
QtConcurrent::run(CSandBox::MergeSnapshotAsync, pProgress, m_FilePath, ID, IsCurrent ? QString() : ChildIDs.first());
QtConcurrent::run(CSandBox::MergeSnapshotAsync, pProgress, m_FilePath, ID, IsCurrent ? QString() : ChildIDs.first(), m_Name, m_pAPI);
else
QtConcurrent::run(CSandBox::DeleteSnapshotAsync, pProgress, m_FilePath, ID);
return SB_PROGRESS(OP_ASYNC, pProgress);
@ -549,7 +549,11 @@ SB_STATUS CSandBox__CleanupSnapshot(const QString& Folder)
return SB_OK;
}
void CSandBox::MergeSnapshotAsync(const CSbieProgressPtr& pProgress, const QString& BoxPath, const QString& TargetID, const QString& SourceID)
// path flags, saved to file
#define FILE_DELETED_FLAG 0x0001
#define FILE_RELOCATION_FLAG 0x0002
void CSandBox::MergeSnapshotAsync(const CSbieProgressPtr& pProgress, const QString& BoxPath, const QString& TargetID, const QString& SourceID, const QString& BoxName, class CSbieAPI* pAPI)
{
//
// Targe is to be removed;
@ -563,8 +567,82 @@ void CSandBox::MergeSnapshotAsync(const CSbieProgressPtr& pProgress, const QStri
QString SourceFolder = IsCurrent ? BoxPath : (BoxPath + "\\snapshot-" + SourceID);
QString TargetFolder = BoxPath + "\\snapshot-" + TargetID;
auto GetBoxedPath = [BoxPath, BoxName, pAPI](const QString& Path, const QString& TargetFolder) {
QString SubPath = pAPI->GetBoxedPath(BoxName, Path).mid(BoxPath.length());
return TargetFolder + SubPath;
};
SB_STATUS Status = SB_OK;
// apply source FilePaths.dat on the targetfolder
if (QFile::exists(SourceFolder + "\\FilePaths.dat"))
{
QFile datSource(SourceFolder + "\\FilePaths.dat");
if (datSource.open(QFile::ReadOnly))
{
QStringList datData = QString::fromWCharArray((wchar_t*)datSource.readAll().data(), datSource.size() / sizeof(wchar_t)).split("\n");
// process relocations
foreach (const QString& Line, datData) {
QStringList Data = Line.trimmed().split("|");
QString Path = Data[0];
if (Path.isEmpty()) continue;
Path = GetBoxedPath(Path, TargetFolder);
int Flags = Data.size() >= 2 ? Data[1].toInt() : 0;
if (Flags & FILE_RELOCATION_FLAG)
{
QString Relocation = Data.size() >= 3 ? GetBoxedPath(Data[2], TargetFolder) : QString();
SNtObject ntSrc(L"\\??\\" + Relocation.toStdWString());
if (NtIo_FileExists(&ntSrc.attr)) {
SNtObject ntOld(L"\\??\\" + Path.toStdWString());
NTSTATUS status = NtIo_DeleteFolderRecursively(&ntOld.attr, [](const WCHAR* info, void* param) {
CSbieProgress* pProgress = (CSbieProgress*)param;
pProgress->ShowMessage(CSandBox::tr("Deleting folder: %1").arg(QString::fromWCharArray(info)));
return !pProgress->IsCanceled();
}, pProgress.data());
if (NT_SUCCESS(status))
{
QStringList PathX = Path.split("\\");
QString Name = PathX.takeLast();
SNtObject ntDest(L"\\??\\" + PathX.join("\\").toStdWString());
status = NtIo_RenameFolder(&ntSrc.attr, &ntDest.attr, Name.toStdWString().c_str());
}
}
}
}
// process deletions
foreach (const QString& Line, datData) {
QStringList Data = Line.trimmed().split("|");
QString Path = Data[0];
if (Path.isEmpty()) continue;
Path = GetBoxedPath(Path, TargetFolder);
int Flags = Data.size() >= 2 ? Data[1].toInt() : 0;
if (Flags & FILE_DELETED_FLAG)
{
SNtObject ntPath(L"\\??\\" + Path.toStdWString());
NTSTATUS status = NtIo_DeleteFile(ntPath, [](const WCHAR* info, void* param) {
CSbieProgress* pProgress = (CSbieProgress*)param;
pProgress->ShowMessage(CSandBox::tr("Deleting: %1").arg(QString::fromWCharArray(info)));
return !pProgress->IsCanceled();
}, pProgress.data());
}
}
}
}
// merge source folders to the target snapshot
foreach(const QString& BoxSubFolder, CSandBox__BoxSubFolders)
{
Status = CSandBox__MergeFolders(pProgress, TargetFolder + "\\" + BoxSubFolder, SourceFolder + "\\" + BoxSubFolder);
@ -576,6 +654,32 @@ void CSandBox::MergeSnapshotAsync(const CSbieProgressPtr& pProgress, const QStri
if(!Status.IsError())
{
// merge DeleteV2 file entries
if (QFile::exists(SourceFolder + "\\FilePaths.dat")) {
QFile datSource(SourceFolder + "\\FilePaths.dat");
if (datSource.open(QFile::ReadOnly)) {
QFile datTarget(TargetFolder + "\\FilePaths.dat");
if (datTarget.open(QFile::ReadWrite)) {
// merge with target
datTarget.seek(datTarget.size());
datTarget.write(datSource.readAll());
// remove source
datSource.close();
datSource.remove();
}
}
}
// copy other data files from source to target
foreach(const SBoxDataFile& BoxDataFile, CSandBox__BoxDataFiles)
{
if (!QFile::exists(SourceFolder + "\\" + BoxDataFile.Name))
continue;
QFile::remove(TargetFolder + "\\" + BoxDataFile.Name);
QFile::rename(SourceFolder + "\\" + BoxDataFile.Name, TargetFolder + "\\" + BoxDataFile.Name);
}
if (IsCurrent)
{
// move all folders out of the snapshot to root
@ -586,6 +690,12 @@ void CSandBox::MergeSnapshotAsync(const CSbieProgressPtr& pProgress, const QStri
break;
}
// move all data files out of the snapshot to root
foreach(const SBoxDataFile& BoxDataFile, CSandBox__BoxDataFiles)
{
QFile::rename(TargetFolder + "\\" + BoxDataFile.Name, SourceFolder + "\\" + BoxDataFile.Name);
}
// delete snapshot rest
if (!Status.IsError())
Status = CSandBox__CleanupSnapshot(TargetFolder);
@ -595,7 +705,7 @@ void CSandBox::MergeSnapshotAsync(const CSbieProgressPtr& pProgress, const QStri
// delete rest of source snpshot
Status = CSandBox__CleanupSnapshot(SourceFolder);
// rename target snapshot o source snapshot
// rename target snapshot to source snapshot
if (!Status.IsError())
Status = CSandBox__MoveFolder(TargetFolder, BoxPath, "snapshot-" + SourceID);
}

View File

@ -86,7 +86,7 @@ protected:
static void CleanBoxAsync(const CSbieProgressPtr& pProgress, const QStringList& BoxFolders);
static void DeleteSnapshotAsync(const CSbieProgressPtr& pProgress, const QString& BoxPath, const QString& ID);
static void MergeSnapshotAsync(const CSbieProgressPtr& pProgress, const QString& BoxPath, const QString& TargetID, const QString& SourceID);
static void MergeSnapshotAsync(const CSbieProgressPtr& pProgress, const QString& BoxPath, const QString& TargetID, const QString& SourceID, const QString& BoxName, class CSbieAPI* pAPI);
QString m_FilePath;
QString m_RegPath;