diff --git a/CHANGELOG.md b/CHANGELOG.md
index ab1fb828..d0e8d8b1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,15 +5,44 @@ This project adheres to [Semantic Versioning](http://semver.org/).
+
+# [1.1.0 / 5.56.0] - 2022-01-??
+
+### Added
+- added support for NtRenameKey (this requires UseRegDeleteV2=y) [#205](https://github.com/sandboxie-plus/Sandboxie/issues/205)
+- added options menu command to reset the GUI [#1589](https://github.com/sandboxie-plus/Sandboxie/issues/1589)
+
+### Changed
+- reworked the mechanism sandboxie uses to mark host files as deleted
+-- the new behavioure creates a data file in the box root FilePaths.dat instead of creating dummy files
+-- it can be enabled with UseFileDeleteV2=y sane for the registry UseRegDeleteV2=y using RegPaths.dat
+- disabled a couple driver based workarounds for boxes in compartment mode as then thay should not be required
+
+
+### Fixed
+- fixed folder rename issues (this requires UseFileDeleteV2=y) [#71](https://github.com/sandboxie-plus/Sandboxie/issues/71)
+
+
+
+
# [1.0.10 / 5.55.10] - 2022-01-??
### Added
-- added option to show only boxes in hray with runnign processes [#1186](https://github.com/sandboxie-plus/Sandboxie/issues/1186)
-todo:- add reset ui ooption
+- added option to show only boxes in tray with runnign processes [#1186](https://github.com/sandboxie-plus/Sandboxie/issues/1186)
+-- additional option show only pinned bixes, in box options a bix can be set to be always shown in theay list (Pinned)
+- add reset ui option
+- added 'Run Un-Sandboxed' context menu option
+- added new trigger "OnBoxDelete" that allows to specify a command that is run UNBOXED just before the box content gets deleted
+-- note: this can be used as a replacemetn to the DeleteCommand [#591](https://github.com/sandboxie-plus/Sandboxie/issues/591)
+- sellected box operations (deletion) no longer show the progress dialog [1061](https://github.com/sandboxie-plus/Sandboxie/issues/1061)
+-- instead a box with a running operation show a blinking hour glass icon, the context menu can be used to cancel the operation
### Changed
- HideHostProcess=program.exe can now be used to hide sandboxie services [#1336](https://github.com/sandboxie-plus/Sandboxie/issues/1336)
-- updater blocking is now done using a template with BlockSoftwareUpdaters
+- updater blocking is now done using a template called BlockSoftwareUpdaters
+- enchanced "StartProgram=..." making "StartCommand=..." obsolete
+-- for same functionality as "StartCommand=..." use "StartProgram=%SbieHome%\Start.exe ..."
+- merged "Auto Start" General tab with the "Auto Exec" Advanced tab into a universal"Triggers" Advanced tab
### Fixed
- fixed a couple issues with the new breakout process feature and improved security (thanks Diversenok)
@@ -22,8 +51,8 @@ todo:- add reset ui ooption
- fixed issue handling commandline invokation [#1133](https://github.com/sandboxie-plus/Sandboxie/issues/1133)
- fixed ui issue with main window state when switching always on top attribute [#1169](https://github.com/sandboxie-plus/Sandboxie/issues/1169)
- fixed issue with box context menu in tray list [1106](https://github.com/sandboxie-plus/Sandboxie/issues/1106)
-
-
+- fixed issue with "AutoExec=..."
+- fixed issues canceling box deletion operations didn't working [1061](https://github.com/sandboxie-plus/Sandboxie/issues/1061)
diff --git a/Sandboxie/common/my_version.h b/Sandboxie/common/my_version.h
index 1d86d4ef..ade0b98b 100644
--- a/Sandboxie/common/my_version.h
+++ b/Sandboxie/common/my_version.h
@@ -21,8 +21,8 @@
#ifndef _MY_VERSION_H
#define _MY_VERSION_H
-#define MY_VERSION_BINARY 5,55,10
-#define MY_VERSION_STRING "5.55.10"
+#define MY_VERSION_BINARY 5,56,0
+#define MY_VERSION_STRING "5.56.0"
#define MY_VERSION_COMPAT "5.55.0" // this refers to the driver ABI compatibility
// These #defines are used by either Resource Compiler or NSIS installer
diff --git a/Sandboxie/core/dll/SboxDll.vcxproj b/Sandboxie/core/dll/SboxDll.vcxproj
index 7a73dd19..f0470d0c 100644
--- a/Sandboxie/core/dll/SboxDll.vcxproj
+++ b/Sandboxie/core/dll/SboxDll.vcxproj
@@ -96,6 +96,7 @@
true
false
+ WITH_DEBUG;%(PreprocessorDefinitions)
ntdll.lib;uuid.lib;kernel32.lib
@@ -117,6 +118,7 @@
Default
true
false
+ WITH_DEBUG;%(PreprocessorDefinitions)
ntdll.lib;uuid.lib;kernel32.lib
@@ -243,6 +245,12 @@
+
+ true
+ true
+ true
+ true
+
true
true
@@ -279,6 +287,18 @@
true
true
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
@@ -291,6 +311,7 @@
+
@@ -305,6 +326,12 @@
+
+ true
+ true
+ true
+ true
+
true
true
@@ -427,6 +454,7 @@
+
diff --git a/Sandboxie/core/dll/SboxDll.vcxproj.filters b/Sandboxie/core/dll/SboxDll.vcxproj.filters
index 0e744e64..048cd5b6 100644
--- a/Sandboxie/core/dll/SboxDll.vcxproj.filters
+++ b/Sandboxie/core/dll/SboxDll.vcxproj.filters
@@ -6,11 +6,9 @@
-
-
@@ -218,6 +216,25 @@
debug
+
+ file
+
+
+ key
+
+
+ obj
+
+
+ obj
+
+
+
+ file
+
+
+ file
+
@@ -255,9 +272,6 @@
api
-
- com
-
common
@@ -312,6 +326,12 @@
debug
+
+ obj
+
+
+ obj
+
@@ -373,6 +393,9 @@
{db0f9820-8908-4325-96f9-69c82fa9e268}
+
+ {05955a21-494a-4624-854e-d7c9b1e33401}
+
diff --git a/Sandboxie/core/dll/debug.c b/Sandboxie/core/dll/debug.c
index f64a3fd6..2c0ed036 100644
--- a/Sandboxie/core/dll/debug.c
+++ b/Sandboxie/core/dll/debug.c
@@ -420,6 +420,33 @@ void DbgPrint(const char* format, ...)
}
+
+//---------------------------------------------------------------------------
+// DbgPrint
+//---------------------------------------------------------------------------
+
+
+void DbgTrace(const char* format, ...)
+{
+ va_list va_args;
+ va_start(va_args, format);
+
+ char *tmp1 = Dll_AllocTemp(510);
+
+ extern int(*P_vsnprintf)(char *_Buffer, size_t Count, const char * const, va_list Args);
+ P_vsnprintf(tmp1, 510, format, va_args);
+
+ WCHAR *tmp2 = Dll_AllocTemp(510*sizeof(WCHAR));
+ Sbie_snwprintf((WCHAR *)tmp2, 510, L"%S", tmp1);
+
+ SbieApi_MonitorPut2(MONITOR_OTHER | MONITOR_TRACE, tmp2, FALSE);
+
+ Dll_Free(tmp1);
+
+ va_end(va_args);
+}
+
+
//---------------------------------------------------------------------------
diff --git a/Sandboxie/core/dll/debug.h b/Sandboxie/core/dll/debug.h
index 0a0a02e0..b07afaaf 100644
--- a/Sandboxie/core/dll/debug.h
+++ b/Sandboxie/core/dll/debug.h
@@ -43,6 +43,7 @@
int Debug_Init(void);
void DbgPrint(const char* format, ...);
+void DbgTrace(const char* format, ...);
#endif WITH_DEBUG
diff --git a/Sandboxie/core/dll/dll.h b/Sandboxie/core/dll/dll.h
index 0775a846..21471802 100644
--- a/Sandboxie/core/dll/dll.h
+++ b/Sandboxie/core/dll/dll.h
@@ -48,7 +48,8 @@ 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 NAME_BUFFER_COUNT 3
+#define MOVE_NAME_BUFFER 3
+#define NAME_BUFFER_COUNT 4
#define NAME_BUFFER_DEPTH 24
@@ -280,6 +281,7 @@ extern BOOLEAN Dll_RestrictedToken;
extern BOOLEAN Dll_ChromeSandbox;
extern BOOLEAN Dll_FirstProcessInBox;
extern BOOLEAN Dll_CompartmentMode;
+//extern BOOLEAN Dll_AlernateIpcNaming;
extern ULONG Dll_ImageType;
@@ -348,6 +350,11 @@ void Dll_FreeTlsData(void);
WCHAR *Dll_GetTlsNameBuffer(THREAD_DATA *data, ULONG which, ULONG size);
void Dll_PushTlsNameBuffer(THREAD_DATA *data);
void Dll_PopTlsNameBuffer(THREAD_DATA *data);
+//void Dll_PushTlsNameBuffer_(THREAD_DATA *data, char* func);
+//void Dll_PopTlsNameBuffer_(THREAD_DATA *data, char* func);
+//#define Dll_PushTlsNameBuffer(x) Dll_PushTlsNameBuffer_(x, __FUNCTION__)
+//#define Dll_PopTlsNameBuffer(x) Dll_PopTlsNameBuffer_(x, __FUNCTION__)
+
//---------------------------------------------------------------------------
@@ -444,7 +451,7 @@ NTSTATUS Pipe_NtCreateFile(
void *EaBuffer,
ULONG EaLength);
-void File_DuplicateRecover(HANDLE OldFileHandle, HANDLE NewFileHandle);
+void Handle_SetupDuplicate(HANDLE OldFileHandle, HANDLE NewFileHandle);
void File_DoAutoRecover(BOOLEAN force);
@@ -477,9 +484,7 @@ BOOLEAN File_IsBlockedNetParam(const WCHAR *BoxName);
void File_GetSetDeviceMap(WCHAR *DeviceMap96);
-typedef void(*P_CloseHandler)(HANDLE handle);
-BOOLEAN File_RegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler);
-BOOLEAN File_UnRegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler);
+void File_NotifyRecover(HANDLE FileHandle);
//---------------------------------------------------------------------------
// Functions (key)
@@ -612,7 +617,7 @@ BOOLEAN Win32_Init(HMODULE hmodule);
// Functions (init for DllMain)
//---------------------------------------------------------------------------
-BOOLEAN File_InitHandles(void);
+BOOLEAN Handle_Init(void);
BOOLEAN Key_Init(void);
diff --git a/Sandboxie/core/dll/dllmain.c b/Sandboxie/core/dll/dllmain.c
index 6d3af3b3..9728b6d3 100644
--- a/Sandboxie/core/dll/dllmain.c
+++ b/Sandboxie/core/dll/dllmain.c
@@ -87,6 +87,7 @@ BOOLEAN Dll_RestrictedToken = FALSE;
BOOLEAN Dll_ChromeSandbox = FALSE;
BOOLEAN Dll_FirstProcessInBox = FALSE;
BOOLEAN Dll_CompartmentMode = FALSE;
+//BOOLEAN Dll_AlernateIpcNaming = FALSE;
ULONG Dll_ImageType = DLL_IMAGE_UNSPECIFIED;
@@ -326,6 +327,28 @@ _FX void Dll_InitInjected(void)
Dll_BoxKeyPathLen = wcslen(Dll_BoxKeyPath);
Dll_BoxIpcPathLen = wcslen(Dll_BoxIpcPath);
+ // Dll_AlernateIpcNaming = SbieApi_QueryConfBool(NULL, L"UseAlernateIpcNaming", FALSE);
+ // if (Dll_AlernateIpcNaming) {
+ //
+ // //
+ // // instead of using a separate namespace
+ // // just replace all \ with _ and use it as a sufix rather then an actual path
+ // // similarly a its done for named pipes already
+ // // this approche can help to reduce teh footprint when running in portable mode
+ // // alternatively we could create volatile entries under AppContainerNamedObjects
+ // //
+ //
+ // WCHAR* ptr = (WCHAR*)Dll_BoxIpcPath;
+ // while (*ptr) {
+ // WCHAR *ptr2 = wcschr(ptr, L'\\');
+ // if (ptr2) {
+ // ptr = ptr2;
+ // *ptr = L'_';
+ // } else
+ // ptr += wcslen(ptr);
+ // }
+ // }
+
//
// check if process SID is LocalSystem
//
@@ -348,7 +371,7 @@ _FX void Dll_InitInjected(void)
Dll_FixWow64Syscall();
if (ok)
- ok = File_InitHandles();
+ ok = Handle_Init();
if (ok)
ok = Obj_Init();
@@ -418,7 +441,7 @@ _FX void Dll_InitInjected(void)
if (ok)
ok = Gui_InitConsole1();
- if (ok)
+ if (ok) // Note: Ldr_Init may cause rpcss to be started early
ok = Ldr_Init(); // last to initialize
//
diff --git a/Sandboxie/core/dll/dllmem.c b/Sandboxie/core/dll/dllmem.c
index d63439aa..36c62c02 100644
--- a/Sandboxie/core/dll/dllmem.c
+++ b/Sandboxie/core/dll/dllmem.c
@@ -24,6 +24,7 @@
#include "dll.h"
#include "common/pool.h"
#include
+#include "debug.h"
//---------------------------------------------------------------------------
@@ -372,8 +373,10 @@ ALIGNED WCHAR *Dll_GetTlsNameBuffer(
//---------------------------------------------------------------------------
+//ALIGNED void Dll_PushTlsNameBuffer_(THREAD_DATA *data, char* func)
ALIGNED void Dll_PushTlsNameBuffer(THREAD_DATA *data)
{
+ //DbgTrace("Dll_PushTlsNameBuffer, %s, %d\r\n", func, data->depth);
++data->depth;
if (data->depth > NAME_BUFFER_DEPTH - 4)
SbieApi_Log(2310, L"%d", data->depth);
@@ -388,8 +391,11 @@ ALIGNED void Dll_PushTlsNameBuffer(THREAD_DATA *data)
//---------------------------------------------------------------------------
+//_FX void Dll_PopTlsNameBuffer_(THREAD_DATA *data, char* func)
_FX void Dll_PopTlsNameBuffer(THREAD_DATA *data)
{
+ //DbgTrace("Dll_PopTlsNameBuffer, %s, %d\r\n", func, data->depth-1);
+
//
// debug checks: the name buffer is allocated at least 64 bytes
// more than needed. fill these with 0xCC, andd check that later
diff --git a/Sandboxie/core/dll/file.c b/Sandboxie/core/dll/file.c
index 1f79d8c2..4562d2e7 100644
--- a/Sandboxie/core/dll/file.c
+++ b/Sandboxie/core/dll/file.c
@@ -23,11 +23,12 @@
#define NOGDI
#include "dll.h"
#include "obj.h"
+#include "handle.h"
#include
#include
#include "core/svc/FileWire.h"
#include "core/svc/InteractiveWire.h"
-
+#include "debug.h"
//---------------------------------------------------------------------------
// Defines
@@ -97,19 +98,13 @@ typedef struct _FILE_LINK FILE_LINK;
typedef struct _FILE_DRIVE FILE_DRIVE;
-typedef struct _FILE_SNAPSHOT {
- WCHAR ID[17];
- ULONG IDlen;
- ULONG ScramKey;
- //WCHAR Name[34];
- struct _FILE_SNAPSHOT* Parent;
-} FILE_SNAPSHOT, *PFILE_SNAPSHOT;
-
//---------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------
+static ULONG File_FindBoxPrefixLength(const WCHAR* CopyPath);
+
SBIEDLL_EXPORT NTSTATUS File_GetName(
HANDLE RootDirectory, UNICODE_STRING *ObjectName,
@@ -139,10 +134,6 @@ static NTSTATUS File_GetName_FromFileId(
OBJECT_ATTRIBUTES *ObjectAttributes,
WCHAR **OutTruePath, WCHAR **OutCopyPath);
-static WCHAR* File_MakeSnapshotPath(FILE_SNAPSHOT* Cur_Snapshot, WCHAR* CopyPath);
-
-static BOOLEAN File_FindSnapshotPath(WCHAR** CopyPath);
-
static ULONG File_MatchPath(const WCHAR *path, ULONG *FileFlags);
static ULONG File_MatchPath2(const WCHAR *path, ULONG *FileFlags, BOOLEAN bCheckObjectExists, BOOLEAN bMonitorLog);
@@ -193,17 +184,10 @@ static BOOLEAN File_CheckDeletedParent(WCHAR *CopyPath);
static NTSTATUS File_CreatePath(WCHAR *TruePath, WCHAR *CopyPath);
-static NTSTATUS File_CreatePath_2(
- HANDLE *handle, OBJECT_ATTRIBUTES *objattrs,
- IO_STATUS_BLOCK *IoStatusBlock, ULONG FileAttributes);
-
static NTSTATUS File_MigrateFile(
const WCHAR *TruePath, const WCHAR *CopyPath,
BOOLEAN IsWritePath, BOOLEAN WithContents);
-static const BOOLEAN File_MigrateFile_ManualBypass(
- const WCHAR *TruePath, ULONGLONG file_size);
-
static NTSTATUS File_CopyShortName(
const WCHAR *TruePath, const WCHAR *CopyPath);
@@ -274,10 +258,6 @@ static BOOLEAN File_RecordRecover(HANDLE FileHandle, const WCHAR *TruePath);
static NTSTATUS File_SetReparsePoint(
HANDLE FileHandle, PREPARSE_DATA_BUFFER Data, ULONG DataLen);
-static void File_ScrambleShortName(WCHAR* ShortName, CCHAR* ShortNameLength, ULONG ScramKey);
-
-static void File_UnScrambleShortName(WCHAR* ShortName, ULONG ScramKey);
-
static NTSTATUS File_GetFileName(HANDLE FileHandle, ULONG NameLen, WCHAR *NameBuf);
//---------------------------------------------------------------------------
@@ -357,15 +337,15 @@ static ULONG File_PublicUserLen = 0;
static BOOLEAN File_DriveAddSN = FALSE;
+static BOOLEAN File_Delete_v2 = FALSE;
+static BOOLEAN File_NoReparse = FALSE;
+
static BOOLEAN File_Windows2000 = FALSE;
static WCHAR *File_AltBoxPath = NULL;
static ULONG File_AltBoxPathLen = 0;
-static FILE_SNAPSHOT *File_Snapshot = NULL;
-static ULONG File_Snapshot_Count = 0;
-
//---------------------------------------------------------------------------
// File (other modules)
@@ -375,7 +355,10 @@ static ULONG File_Snapshot_Count = 0;
#include
#include "file_link.c"
#include "file_pipe.c"
+#include "file_del.c"
+#include "file_snapshots.c"
#include "file_dir.c"
+#include "file_recovery.c"
#include "file_misc.c"
#include "file_copy.c"
#include "file_init.c"
@@ -468,7 +451,17 @@ _FX NTSTATUS File_GetName(
if (RootDirectory) {
- UNICODE_STRING *uni;
+ UNICODE_STRING *uni = NULL;
+
+ name = Handle_GetRelocationPath(RootDirectory, objname_len + sizeof(UNICODE_STRING));
+ if (name) {
+
+ length = (wcslen(name) + 1) * sizeof(WCHAR);
+ uni = ((UCHAR*)name) + (length + objname_len);
+ RtlInitUnicodeString(uni, name);
+
+ }
+ else {
length = 256;
name = Dll_GetTlsNameBuffer(
@@ -507,6 +500,7 @@ _FX NTSTATUS File_GetName(
return status;
uni = &((OBJECT_NAME_INFORMATION *)name)->Name;
+ }
#ifdef WOW64_FS_REDIR
//
@@ -1360,6 +1354,7 @@ _FX WCHAR *File_GetName_TranslateSymlinks(
if (NT_SUCCESS(status))
break;
+ if (!Dll_CompartmentMode) // NoDriverAssist
if (status == STATUS_ACCESS_DENIED &&
objname.Length <= 1020 * sizeof(WCHAR)) {
@@ -1503,40 +1498,6 @@ copy_suffix:
}
-//---------------------------------------------------------------------------
-// File_MakeSnapshotPath
-//---------------------------------------------------------------------------
-
-
-_FX WCHAR* File_MakeSnapshotPath(FILE_SNAPSHOT* Cur_Snapshot, WCHAR* CopyPath)
-{
- if (!Cur_Snapshot)
- return NULL;
-
- ULONG length = wcslen(CopyPath);
- ULONG prefixLen = 0;
- if (length >= Dll_BoxFilePathLen && 0 == Dll_NlsStrCmp(CopyPath, Dll_BoxFilePath, Dll_BoxFilePathLen))
- prefixLen = Dll_BoxFilePathLen;
- if (File_AltBoxPath && length >= File_AltBoxPathLen && 0 == Dll_NlsStrCmp(CopyPath, File_AltBoxPath, File_AltBoxPathLen))
- prefixLen = File_AltBoxPathLen;
-
- if (prefixLen == 0)
- return NULL;
-
-
- THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
-
- WCHAR* TmplName = Dll_GetTlsNameBuffer(TlsData, TMPL_NAME_BUFFER, (wcslen(CopyPath) + 9 + 17 + 1) * sizeof(WCHAR));
-
- wcsncpy(TmplName, CopyPath, prefixLen + 1);
- wcscpy(TmplName + prefixLen + 1, L"snapshot-");
- wcscpy(TmplName + prefixLen + 1 + 9, Cur_Snapshot->ID);
- wcscpy(TmplName + prefixLen + 1 + 9 + Cur_Snapshot->IDlen, CopyPath + prefixLen);
-
- return TmplName;
-}
-
-
//---------------------------------------------------------------------------
// File_GetName_ExpandShortNames2
//---------------------------------------------------------------------------
@@ -2308,50 +2269,6 @@ finish:
}
-//---------------------------------------------------------------------------
-// File_FindSnapshotPath
-//---------------------------------------------------------------------------
-
-
-_FX BOOLEAN File_FindSnapshotPath(WCHAR** CopyPath)
-{
- NTSTATUS status;
- OBJECT_ATTRIBUTES objattrs;
- UNICODE_STRING objname;
- ULONG FileType;
-
- InitializeObjectAttributes(&objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
-
- //
- // When working with snapshots the actual "CopyFile" may be located in a snapshot directory.
- // To deal with that when the file is not in the active box directory we look through the snapshots,
- // When we find it we update the path to point to the snapshot containing the file.
- //
-
- RtlInitUnicodeString(&objname, *CopyPath);
- status = File_GetFileType(&objattrs, FALSE, &FileType, NULL);
- if (!(status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND))
- return FALSE; // file is present directly in copy path
-
- for (FILE_SNAPSHOT* Cur_Snapshot = File_Snapshot; Cur_Snapshot != NULL; Cur_Snapshot = Cur_Snapshot->Parent)
- {
- WCHAR* TmplName = File_MakeSnapshotPath(Cur_Snapshot, *CopyPath);
- if (!TmplName)
- break;
-
- RtlInitUnicodeString(&objname, TmplName);
- status = File_GetFileType(&objattrs, FALSE, &FileType, NULL);
- if (!(status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND))
- {
- *CopyPath = TmplName;
- return TRUE;
- }
- }
-
- return FALSE; // this file is not sandboxed
-}
-
-
//---------------------------------------------------------------------------
// File_NtOpenFile
//---------------------------------------------------------------------------
@@ -2408,7 +2325,8 @@ _FX NTSTATUS File_NtCreateFile(
// File_NtCreateFileImpl
//---------------------------------------------------------------------------
-/*
+
+#ifdef WITH_DEBUG_
static P_NtCreateFile __sys_NtCreateFile_ = NULL;
_FX NTSTATUS File_MyCreateFile(
@@ -2430,18 +2348,18 @@ _FX NTSTATUS File_MyCreateFile(
CreateOptions, EaBuffer, EaLength);
if (ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer
- && _wcsicmp(ObjectAttributes->ObjectName->Buffer, L"\\??\\PhysicalDrive0") == 0)
+ && wcsstr(ObjectAttributes->ObjectName->Buffer, L"ext-ms-win-branding-winbrand-l1-1-0.dll") != 0)
{
- WCHAR text[1024];
- Sbie_snwprintf(text, 1024, L"%s <%08X>", ObjectAttributes->ObjectName->Buffer, status);
- SbieApi_MonitorPut(MONITOR_OTHER, text);
+ return status;
}
+ //if (NT_SUCCESS(status)) DbgPrint("%p: %p\r\n", _ReturnAddress(), *FileHandle);
+
status = StopTailCallOptimization(status);
return status;
-}*/
-
+}
+#endif
_FX NTSTATUS File_NtCreateFileImpl(
HANDLE *FileHandle,
@@ -2472,7 +2390,10 @@ _FX NTSTATUS File_NtCreateFileImpl(
BOOLEAN IsEmptyCopyFile;
BOOLEAN AlreadyReparsed;
UCHAR HaveTrueFile;
- BOOLEAN HaveSnapshotFile, HaveSnapshotParent;
+ BOOLEAN HaveSnapshotParent;
+ ULONG TruePathFlags;
+ WCHAR* OriginalPath;
+ BOOLEAN TrueOpened;
//char *pPtr = NULL;
//if (wcsstr(Dll_ImageName, L"chrome.exe") != 0) {
@@ -2481,13 +2402,15 @@ _FX NTSTATUS File_NtCreateFileImpl(
// // __debugbreak();
//}
- /*if (__sys_NtCreateFile_ == NULL)
+#ifdef WITH_DEBUG_
+ if (__sys_NtCreateFile_ == NULL)
{
__sys_NtCreateFile_ = __sys_NtCreateFile;
__sys_NtCreateFile = File_MyCreateFile;
}
+#endif
- if (ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer
+ /*if (ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer
&& _wcsicmp(ObjectAttributes->ObjectName->Buffer, L"\\??\\PhysicalDrive0") == 0)
{
return __sys_NtCreateFile(
@@ -2497,7 +2420,7 @@ _FX NTSTATUS File_NtCreateFileImpl(
}*/
/*if (ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer
- && wcsstr(ObjectAttributes->ObjectName->Buffer, L"Game.ini") != NULL ) {
+ && wcsstr(ObjectAttributes->ObjectName->Buffer, L"socket_") != NULL ) {
while (! IsDebuggerPresent()) { OutputDebugString(L"BREAK\n"); Sleep(500); }
__debugbreak();
}*/
@@ -2543,7 +2466,8 @@ _FX NTSTATUS File_NtCreateFileImpl(
DesiredAccess &= ~ACCESS_SYSTEM_SECURITY;
}
-
+ OriginalPath = NULL;
+ TrueOpened = FALSE;
__try {
@@ -2781,6 +2705,8 @@ ReparseLoop:
if (ReparsedPath)
Dll_Free(ReparsedPath);
+ if (NT_SUCCESS(status)) TrueOpened = TRUE;
+
//
// if we got STATUS_OBJECT_PATH_NOT_FOUND on an open path, meaning
// that parent directories are missing outside the sandbox, then
@@ -2818,25 +2744,6 @@ ReparseLoop:
if (! NT_SUCCESS(status))
__leave;
- HaveSnapshotFile = FALSE;
- HaveSnapshotParent = FALSE;
-
- if (File_Snapshot != NULL) {
-
- WCHAR* TmplPath = CopyPath;
-
- File_FindSnapshotPath(&TmplPath);
-
- if (TmplPath != CopyPath) {
-
- HaveSnapshotFile = TRUE;
-
- TruePath = Dll_GetTlsNameBuffer(TlsData, TRUE_NAME_BUFFER, (wcslen(TmplPath) + 1) * sizeof(WCHAR));
- wcscpy(TruePath, TmplPath);
- }
- }
-
-
//
// if TruePath and CopyPath contain colons that indicate an NTFS
// alternate data stream, we remove these for now
@@ -2860,6 +2767,7 @@ ReparseLoop:
// abort early if the parent of CopyPath exists but marked deleted
//
+ if (!File_Delete_v2)
if (File_CheckDeletedParent(CopyPath)) {
status = STATUS_OBJECT_PATH_NOT_FOUND;
__leave;
@@ -2897,6 +2805,20 @@ ReparseLoop:
RtlInitUnicodeString(&objname, CopyPath);
status = File_GetFileType(&objattrs, FALSE, &FileType, &IsEmptyCopyFile);
+
+ HaveSnapshotParent = FALSE;
+
+ //
+ // Check true path relocation
+ //
+
+ WCHAR* OldTruePath = File_ResolveTruePath(TruePath, CopyPath, &TruePathFlags);
+ if (OldTruePath) {
+ OriginalPath = TruePath;
+ TruePath = OldTruePath;
+ }
+
+
if (NT_SUCCESS(status)) {
ULONG TrueFileType;
@@ -2957,19 +2879,21 @@ ReparseLoop:
if (! HaveCopyParent) {
- WCHAR* TargetName = wcsrchr(CopyPath, L'\\');
- *TargetName = L'\0';
+ WCHAR* ptr1 = wcsrchr(CopyPath, L'\\');
+ *ptr1 = L'\0';
+ //WCHAR* ptr2 = wcsrchr(TruePath, L'\\');
+ //*ptr2 = L'\0';
- WCHAR* TmplPath = CopyPath;
-
- File_FindSnapshotPath(&TmplPath);
-
- if (TmplPath != CopyPath) {
+ Dll_PushTlsNameBuffer(TlsData);
+ WCHAR* TmplName = File_FindSnapshotPath(CopyPath);
+ if (TmplName != NULL)
HaveSnapshotParent = TRUE;
- }
- *TargetName = L'\\';
+ Dll_PopTlsNameBuffer(TlsData);
+
+ //*ptr2 = L'\\';
+ *ptr1 = L'\\';
}
//
@@ -3021,7 +2945,19 @@ ReparseLoop:
// otherwise not write-only, so do normal File_GetFileType
//
- status = File_GetFileType(&objattrs, FALSE, &FileType, NULL);
+ status = STATUS_SUCCESS;
+ FileType = 0;
+
+ if (TruePathFlags) {
+ if (FILE_PARENT_DELETED(TruePathFlags))
+ status = STATUS_OBJECT_PATH_NOT_FOUND;
+ else if (FILE_IS_DELETED(TruePathFlags))
+ status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ if (NT_SUCCESS(status)) {
+ status = File_GetFileType(&objattrs, FALSE, &FileType, NULL);
+ }
}
//
@@ -3029,7 +2965,7 @@ ReparseLoop:
// check for this and act acrodingly.
//
- if (HaveSnapshotFile) {
+ if (TruePathFlags & FILE_INSNAPSHOT_FLAG) {
if (FileType & TYPE_DELETED) {
@@ -3066,7 +3002,8 @@ ReparseLoop:
HaveTrueFile = 'Y';
else
HaveTrueFile = 'N';
- }
+ } else if (NT_SUCCESS(status))
+ HaveTrueFile = 'y';
if (status == STATUS_OBJECT_PATH_NOT_FOUND)
HaveTrueParent = FALSE;
@@ -3154,6 +3091,8 @@ ReparseLoop:
ShareAccess, CreateDisposition, CreateOptions,
EaBuffer, EaLength);
+ if (NT_SUCCESS(status)) TrueOpened = TRUE;
+
//if (status == STATUS_ACCESS_DENIED)
//{
// while(!IsDebuggerPresent()) Sleep(50); __debugbreak();
@@ -3207,6 +3146,28 @@ ReparseLoop:
}
+ //
+ // abort early if the parent of CopyPath exists but marked deleted
+ //
+
+ if (FILE_PATH_DELETED(TruePathFlags)) { // actual file or its parent
+ if (!HaveCopyFile && (HaveTrueFile == 'Y' || HaveTrueFile == 'y')) { // if this is set status will be success
+
+ FileType = 0;
+ status = STATUS_OBJECT_PATH_NOT_FOUND;
+
+ //
+ // if this is a create operation check if the parent fodler is ok and if so clear the error
+ //
+
+ if (CreateDisposition != FILE_OPEN && CreateDisposition != FILE_OVERWRITE) {
+ if (!FILE_PARENT_DELETED(TruePathFlags)) { // parent not deleted
+ status = STATUS_SUCCESS;
+ }
+ }
+ }
+ }
+
if (! NT_SUCCESS(status))
__leave;
@@ -3290,6 +3251,8 @@ ReparseLoop:
ShareAccess, CreateDisposition, CreateOptions,
EaBuffer, EaLength);
+ if (NT_SUCCESS(status)) TrueOpened = TRUE;
+
__leave;
}
}
@@ -3317,7 +3280,7 @@ ReparseLoop:
if (HaveTrueParent || HaveSnapshotParent) {
- status = File_CreatePath(TruePath, CopyPath);
+ status = File_CreatePath(OriginalPath ? OriginalPath : TruePath, CopyPath);
} else
status = STATUS_OBJECT_PATH_NOT_FOUND;
@@ -3420,6 +3383,8 @@ ReparseLoop:
FileHandle, DesiredAccess, &objattrs, IoStatusBlock,
AllocationSize, FileAttributes, ShareAccess,
CreateDisposition, CreateOptions, EaBuffer, EaLength);
+
+ if (NT_SUCCESS(status)) TrueOpened = TRUE;
}
__leave;
@@ -3432,33 +3397,36 @@ ReparseLoop:
// in this case we physically delete the stale CopyPath.
//
- DeleteChildren = FALSE;
+ if (!File_Delete_v2) {
- if (HaveCopyFile && (FileType & TYPE_DELETED) &&
- (CreateDisposition != FILE_OPEN)) {
+ DeleteChildren = FALSE;
- RtlInitUnicodeString(&objname, CopyPath);
- status = __sys_NtDeleteFile(&objattrs);
+ if (HaveCopyFile && (FileType & TYPE_DELETED) &&
+ (CreateDisposition != FILE_OPEN)) {
- if (! NT_SUCCESS(status))
- __leave;
+ RtlInitUnicodeString(&objname, CopyPath);
+ status = __sys_NtDeleteFile(&objattrs);
- FileType = 0;
+ if (! NT_SUCCESS(status))
+ __leave;
- if ((CreateOptions & FILE_DIRECTORY_FILE) && (! CopyPathColon)) {
+ FileType = 0;
- //
- // if the caller is re-creating a directory that was already
- // deleted (and marked so) in the sandbox, then we should mark
- // everything in it as deleted, after it has been re-created
- //
+ if ((CreateOptions & FILE_DIRECTORY_FILE) && (! CopyPathColon)) {
- DeleteChildren = TRUE;
+ //
+ // if the caller is re-creating a directory that was already
+ // deleted (and marked so) in the sandbox, then we should mark
+ // everything in it as deleted, after it has been re-created
+ //
+
+ DeleteChildren = TRUE;
+ }
}
}
//
- // Note: This is disabled in the driver since Win 10 1903 (see comments in file.c in File_Generic_MyParseProc).
+ // Note: This is disabled in the driver since Win 10 1903 (see my comments in file.c in File_Generic_MyParseProc).
// if the caller specifies write attributes, this is only permitted
// on non-directory files, so we must be sure to tell the driver
//
@@ -3489,7 +3457,7 @@ ReparseLoop:
*CopyPathColon = L':';
RtlInitUnicodeString(&objname, CopyPath);
- if (DeleteOnClose && HaveTrueFile == 'N') {
+ if (DeleteOnClose && (File_Delete_v2 || HaveTrueFile == 'N')) {
CreateOptions |= FILE_DELETE_ON_CLOSE;
DesiredAccess |= DELETE;
@@ -3500,7 +3468,7 @@ ReparseLoop:
&objattrs, IoStatusBlock, AllocationSize, FileAttributes,
ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);
- if (DeleteOnClose && HaveTrueFile == 'N' && (! NT_SUCCESS(status))) {
+ if (!NT_SUCCESS(status) && DeleteOnClose && !File_Delete_v2 && HaveTrueFile == 'N') {
CreateOptions &= ~FILE_DELETE_ON_CLOSE;
DesiredAccess &= ~DELETE;
@@ -3531,6 +3499,8 @@ ReparseLoop:
if (CopyPathColon)
status = STATUS_ACCESS_DENIED;
+ else if (File_Delete_v2)
+ status = File_MarkDeleted_v2(OriginalPath ? OriginalPath : TruePath);
else
status = File_MarkDeleted(*FileHandle, CopyPath);
}
@@ -3543,8 +3513,8 @@ ReparseLoop:
// file was not opened for deletion, but NTFS file systems
// may sometimes persist an (out of date) creation time
//
-
- status = File_SetCreateTime(*FileHandle, CopyPath);
+ if (!File_Delete_v2)
+ status = File_SetCreateTime(*FileHandle, CopyPath);
if (NT_SUCCESS(status)) {
@@ -3555,11 +3525,13 @@ ReparseLoop:
// directory, then mark all its children deleted
//
- if (DeleteChildren) {
+ if (!File_Delete_v2) {
+ if (DeleteChildren) {
- TlsData->file_NtCreateFile_lock = FALSE;
+ TlsData->file_NtCreateFile_lock = FALSE;
- File_MarkChildrenDeleted(TruePath);
+ File_MarkChildrenDeleted(TruePath);
+ }
}
} else {
@@ -3639,10 +3611,21 @@ ReparseLoop:
AllocationSize, FileAttributes, ShareAccess, CreateDisposition,
CreateOptions, EaBuffer, EaLength);
+ if (NT_SUCCESS(status)) TrueOpened = TRUE; // is that right?
+
if (! NT_SUCCESS(status))
status = STATUS_ACCESS_DENIED;
}
+ //
+ // Relocation, if we opened the true file and its relocated set the path info
+ //
+
+ if (TrueOpened && OriginalPath) {
+
+ Handle_SetRelocationPath(*FileHandle, OriginalPath);
+ }
+
//
// finish
//
@@ -3925,8 +3908,10 @@ _FX NTSTATUS File_GetFileType(
if (info.FileAttributes & FILE_ATTRIBUTE_SYSTEM)
type |= TYPE_SYSTEM;
- if (IS_DELETE_MARK(&info.CreationTime))
- type |= TYPE_DELETED;
+ if (!File_Delete_v2) {
+ if (IS_DELETE_MARK(&info.CreationTime))
+ type |= TYPE_DELETED;
+ }
*FileType = type;
@@ -4029,6 +4014,7 @@ _FX NTSTATUS File_CreatePath(WCHAR *TruePath, WCHAR *CopyPath)
ULONG TruePath_len, CopyPath_len;
IO_STATUS_BLOCK IoStatusBlock;
FILE_BASIC_INFORMATION basic_info;
+ BOOLEAN IsDeleted = FALSE;
//
// first we traverse backward along the path, removing the last
@@ -4072,6 +4058,10 @@ _FX NTSTATUS File_CreatePath(WCHAR *TruePath, WCHAR *CopyPath)
savechar = *sep;
*sep = L'\0';
+ sep2 = TruePath + TruePath_len - (CopyPath_len - (sep - CopyPath));
+ savechar2 = *sep2;
+ *sep2 = L'\0';
+
savelength = objname.Length;
savemaximumlength = objname.MaximumLength;
objname.Length = (sep - path) * sizeof(WCHAR);
@@ -4082,20 +4072,33 @@ _FX NTSTATUS File_CreatePath(WCHAR *TruePath, WCHAR *CopyPath)
&IoStatusBlock, NULL, 0, FILE_SHARE_VALID_FLAGS,
FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0);
+ if (File_Delete_v2) {
+ if (!NT_SUCCESS(status)) {
+ IsDeleted = FILE_IS_DELETED(File_IsDeletedEx(TruePath, CopyPath, NULL));
+ }
+ }
+
objname.Length = savelength;
objname.MaximumLength = savemaximumlength;
*sep = savechar;
+ *sep2 = savechar2;
if (NT_SUCCESS(status)) {
- status = __sys_NtQueryInformationFile(
- handle, &IoStatusBlock, &basic_info,
- sizeof(FILE_BASIC_INFORMATION), FileBasicInformation);
+ if (!File_Delete_v2) {
+
+ status = __sys_NtQueryInformationFile(
+ handle, &IoStatusBlock, &basic_info,
+ sizeof(FILE_BASIC_INFORMATION), FileBasicInformation);
+
+ if (NT_SUCCESS(status)) {
+ IsDeleted = IS_DELETE_MARK(&basic_info.CreationTime);
+ }
+ }
NtClose(handle);
- if (NT_SUCCESS(status) &&
- IS_DELETE_MARK(&basic_info.CreationTime)) {
+ if (IsDeleted) {
return STATUS_OBJECT_PATH_NOT_FOUND;
}
@@ -4631,13 +4634,33 @@ _FX NTSTATUS File_QueryFullAttributesDirectoryFile(
HANDLE FileHandle;
NTSTATUS status;
- //
- // try to use SbieApi_OpenFile which will open the file, bypassing
- // ClosedFilePath settings, but only if it a directory file. it
- // returns a handle that can only be used to query file attributes
- //
+ if (!Dll_CompartmentMode) { // NoDriverAssist
+
+ //
+ // try to use SbieApi_OpenFile which will open the file, bypassing
+ // ClosedFilePath settings, but only if it a directory file. it
+ // returns a handle that can only be used to query file attributes
+ //
+
+ status = SbieApi_OpenFile(&FileHandle, TruePath);
+
+ }
+ else {
+
+ OBJECT_ATTRIBUTES objattrs;
+ UNICODE_STRING objname;
+
+ InitializeObjectAttributes(
+ &objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ RtlInitUnicodeString(&objname, TruePath);
+
+ status = __sys_NtCreateFile(
+ &FileHandle, FILE_GENERIC_READ, &objattrs, &MyIoStatusBlock,
+ NULL, 0, FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
+ }
- status = SbieApi_OpenFile(&FileHandle, TruePath);
if (NT_SUCCESS(status)) {
status = __sys_NtQueryInformationFile(
@@ -4807,6 +4830,7 @@ _FX NTSTATUS File_NtQueryFullAttributesFileImpl(
WCHAR *TruePath;
WCHAR *CopyPath;
ULONG FileFlags, FileAttrs, mp_flags;
+ ULONG TruePathFlags;
//
// special case: when it starts, the Windows Explorer process looks
@@ -4911,14 +4935,12 @@ _FX NTSTATUS File_NtQueryFullAttributesFileImpl(
// try NtQueryFullAttributesFile on the CopyPath first
//
+ if (!File_Delete_v2)
if (File_CheckDeletedParent(CopyPath)) {
status = STATUS_OBJECT_PATH_NOT_FOUND;
__leave;
}
- if (File_Snapshot != NULL)
- File_FindSnapshotPath(&CopyPath);
-
RtlInitUnicodeString(&objname, CopyPath);
status = __sys_NtQueryFullAttributesFile(&objattrs, FileInformation);
@@ -4927,9 +4949,12 @@ _FX NTSTATUS File_NtQueryFullAttributesFileImpl(
status != STATUS_OBJECT_NAME_NOT_FOUND &&
status != STATUS_OBJECT_PATH_NOT_FOUND)) {
- if (NT_SUCCESS(status) &&
+ if (!File_Delete_v2) {
+
+ if (NT_SUCCESS(status) &&
IS_DELETE_MARK(&FileInformation->CreationTime))
- status = STATUS_OBJECT_NAME_NOT_FOUND;
+ status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
if (NT_SUCCESS(status))
FileAttrs = FileInformation->FileAttributes;
@@ -4937,6 +4962,14 @@ _FX NTSTATUS File_NtQueryFullAttributesFileImpl(
__leave;
}
+ //
+ // Check true path relocation
+ //
+
+ WCHAR* OldTruePath = File_ResolveTruePath(TruePath, CopyPath, &TruePathFlags);
+ if (OldTruePath)
+ TruePath = OldTruePath;
+
//
// check if this is a write-only path. if the path is not
// the highest level match on the write-only setting, we
@@ -4990,6 +5023,21 @@ _FX NTSTATUS File_NtQueryFullAttributesFileImpl(
status2 = __sys_NtQueryFullAttributesFile(&objattrs, FileInformation);
+ if (TruePathFlags && NT_SUCCESS(status2)) {
+
+ //
+ // if we found only the true file check if its listed as deleted
+ //
+
+ if (FILE_PARENT_DELETED(TruePathFlags)) { // parent deleted
+ status = STATUS_OBJECT_PATH_NOT_FOUND;
+ __leave;
+ } else if (FILE_IS_DELETED(TruePathFlags)) { // path deleted
+ status = STATUS_OBJECT_NAME_NOT_FOUND;
+ __leave;
+ }
+ }
+
if (status2 != STATUS_OBJECT_PATH_NOT_FOUND) {
status = status2;
@@ -6146,16 +6194,7 @@ _FX NTSTATUS File_SetDisposition(
status = STATUS_CANNOT_DELETE;
} else {
- EnterCriticalSection(&File_HandleOnClose_CritSec);
-
- FILE_ON_CLOSE* on_close = map_get(&File_HandleOnClose, FileHandle);
- if (!on_close) {
- on_close = map_insert(&File_HandleOnClose, FileHandle, NULL, sizeof(FILE_ON_CLOSE));
- }
-
- on_close->DeleteOnClose = DeleteOnClose;
-
- LeaveCriticalSection(&File_HandleOnClose_CritSec);
+ Handle_SetDeleteOnClose(FileHandle, DeleteOnClose);
}
/*
@@ -6215,6 +6254,145 @@ _FX NTSTATUS File_NtDeleteFileImpl(OBJECT_ATTRIBUTES *ObjectAttributes)
}
+//---------------------------------------------------------------------------
+// File_RenameOpenFile
+//---------------------------------------------------------------------------
+
+
+_FX LONG File_RenameOpenFile(
+ HANDLE file_handle,
+ const WCHAR* user_dir, const WCHAR* user_name,
+ BOOLEAN replace_if_exists)
+{
+ //
+ // in compartment mode we dont need driver assistance we can do things ourselvs
+ // this code is a port of the same routine in teh driver
+ //
+
+ NTSTATUS status;
+ ULONG user_dir_len = (wcslen(user_dir) + 1) * sizeof(WCHAR);
+ ULONG user_name_len = (wcslen(user_name) + 1) * sizeof(WCHAR);
+ WCHAR *path, *name;
+ FILE_RENAME_INFORMATION *info;
+ ULONG path_len, name_len, info_len;
+ WCHAR save_char;
+ HANDLE dir_handle;
+ OBJECT_ATTRIBUTES objattrs;
+ UNICODE_STRING objname;
+ IO_STATUS_BLOCK IoStatusBlock;
+ ULONG mp_flags;
+
+ //
+ // copy user parameters into consolidated buffer: dir"\"name
+ //
+
+ path_len = user_dir_len + user_name_len + sizeof(WCHAR) * 8;
+ path = Dll_AllocTemp(path_len);
+ if (! path)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ memzero(path, path_len);
+
+ memcpy(path, user_dir, user_dir_len);
+ name = path + wcslen(path);
+ *name = L'\\';
+ memcpy(&name[1], user_name, user_name_len);
+
+ if (wcschr(&name[1], L'\\'))
+ return STATUS_INVALID_PARAMETER;
+
+ //
+ // check if the full target path is an open path, and stop if not
+ //
+
+ mp_flags = File_MatchPath(path, NULL);
+
+ if (!PATH_IS_OPEN(mp_flags) || PATH_IS_CLOSED(mp_flags)) {
+ Dll_Free(path);
+ return STATUS_BAD_INITIAL_PC;
+ }
+
+ //
+ // check if the target directory is an open path, and stop if it is
+ //
+
+ *name = L'\0';
+
+ mp_flags = File_MatchPath(path, NULL);
+
+ if (PATH_IS_OPEN(mp_flags) || PATH_IS_CLOSED(mp_flags)) {
+ Dll_Free(path);
+ return STATUS_BAD_INITIAL_PC;
+ }
+
+ //
+ // now we have established that the full target path name is an
+ // open path, but the parent directory in that path isn't open.
+ // therefore we will open the parent directory for write access
+ // from kernel mode, and do the rename here
+ //
+ // we put a the trailing backslash on the path, so that we can open
+ // the parent directory even when the parent is the root directory
+ //
+
+ save_char = name[1];
+ name[0] = L'\\';
+ name[1] = L'\0';
+
+ InitializeObjectAttributes(
+ &objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ RtlInitUnicodeString(&objname, path);
+
+ status = __sys_NtCreateFile(
+ &dir_handle, FILE_GENERIC_WRITE, &objattrs,
+ &IoStatusBlock, NULL, 0, FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
+
+ if (! NT_SUCCESS(status)) {
+ Dll_Free(path);
+ return status;
+ }
+
+ //
+ // allocate an information buffer, and issue rename request
+ //
+
+ ++name;
+ *name = save_char;
+ name_len = wcslen(name) * sizeof(WCHAR);
+
+ info_len = sizeof(FILE_RENAME_INFORMATION) + name_len + 8;
+ info = Dll_AllocTemp(info_len);
+ if (! info)
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ else {
+
+ memzero(info, info_len);
+ info->ReplaceIfExists = replace_if_exists;
+ info->RootDirectory = dir_handle;
+ info->FileNameLength = name_len;
+ memcpy(info->FileName, name, name_len);
+
+ if (NT_SUCCESS(status)) {
+
+ status = __sys_NtSetInformationFile(
+ file_handle, &IoStatusBlock, //args->file_handle.val, &IoStatusBlock,
+ info, info_len, FileRenameInformation);
+ }
+
+ // FIXME, we may get STATUS_NOT_SAME_DEVICE, however, in most cases,
+ // this API call is used to rename a file inside a folder, rather
+ // than move files across folders, so that isn't a problem
+
+ Dll_Free(info);
+ }
+
+ NtClose(dir_handle);
+ Dll_Free(path);
+ return status;
+}
+
+
//---------------------------------------------------------------------------
// File_RenameFile
//---------------------------------------------------------------------------
@@ -6350,9 +6528,6 @@ _FX NTSTATUS File_RenameFile(
SourceTruePath = Dll_AllocTemp(len);
memcpy(SourceTruePath, TruePath, len);
- if (File_Snapshot != NULL)
- File_FindSnapshotPath(&CopyPath);
-
len = (wcslen(CopyPath) + 1) * sizeof(WCHAR);
SourceCopyPath = Dll_AllocTemp(len);
memcpy(SourceCopyPath, CopyPath, len);
@@ -6418,8 +6593,10 @@ _FX NTSTATUS File_RenameFile(
if (! ReparsedPath)
ReparsedPath = TargetTruePath;
- status = SbieApi_RenameFile(
- SourceHandle, ReparsedPath, TargetFileName, info->ReplaceIfExists);
+ if (!Dll_CompartmentMode) // NoDriverAssist
+ status = SbieApi_RenameFile(SourceHandle, ReparsedPath, TargetFileName, info->ReplaceIfExists);
+ else
+ status = File_RenameOpenFile(SourceHandle, ReparsedPath, TargetFileName, info->ReplaceIfExists);
if (ReparsedPath != TargetTruePath)
Dll_Free(ReparsedPath);
@@ -6545,7 +6722,7 @@ _FX NTSTATUS File_RenameFile(
if (NT_SUCCESS(status)) {
- if (IS_DELETE_MARK(&open_info.CreationTime)) {
+ if (IS_DELETE_MARK(&open_info.CreationTime)) { // !File_Delete_v2 &&
info2->ReplaceIfExists = TRUE;
@@ -6555,16 +6732,26 @@ _FX NTSTATUS File_RenameFile(
}
} else {
+ WCHAR* TargetTruePath2 = TargetTruePath;
- RtlInitUnicodeString(&objname, TargetTruePath);
+ ULONG TargetTruePathFlags = 0;
+ WCHAR* OldTruePath = File_ResolveTruePath(TargetTruePath, TargetCopyPath, &TargetTruePathFlags);
+ if (OldTruePath)
+ TargetTruePath2 = OldTruePath;
- if (!Dll_DigitalGuardian)
+ RtlInitUnicodeString(&objname, TargetTruePath2);
+
+ if (FILE_PATH_DELETED(TargetTruePathFlags)) // File_Delete_v2 &&
+ {
+ status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ else if (!Dll_DigitalGuardian)
{
status = __sys_NtQueryFullAttributesFile(&objattrs, &open_info);
}
else
{
- ULONG mp_flags = File_MatchPath(TargetTruePath, &TargetFlags);
+ ULONG mp_flags = File_MatchPath(TargetTruePath2, &TargetFlags);
if (PATH_IS_OPEN(mp_flags) || !mp_flags)
{
@@ -6640,22 +6827,26 @@ issue_rename:
// is an open path
//
- RtlInitUnicodeString(&objname, TargetCopyPath);
+ if (!File_Delete_v2) {
- status = __sys_NtCreateFile(
- &TargetHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE,
- &objattrs, &IoStatusBlock, NULL, 0, FILE_SHARE_VALID_FLAGS,
- FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
+ RtlInitUnicodeString(&objname, TargetCopyPath);
- if (NT_SUCCESS(status)) {
+ status = __sys_NtCreateFile(
+ &TargetHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+ &objattrs, &IoStatusBlock, NULL, 0, FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
- File_SetCreateTime(TargetHandle, TargetCopyPath);
+ if (NT_SUCCESS(status)) {
- NtClose(TargetHandle);
- TargetHandle = NULL;
+ File_SetCreateTime(TargetHandle, TargetCopyPath);
- } else
- status = STATUS_SUCCESS;
+ NtClose(TargetHandle);
+ TargetHandle = NULL;
+
+ }
+ else
+ status = STATUS_SUCCESS;
+ }
//
// record for recovery
@@ -6673,13 +6864,64 @@ after_rename:
if (SourceFlags & FGN_IS_BOXED_PATH) {
NTSTATUS status2;
- HANDLE handle2;
- FILE_NETWORK_OPEN_INFORMATION open_info;
+ WCHAR* SourceTruePath2 = SourceTruePath;
- RtlInitUnicodeString(&objname, SourceTruePath);
+ WCHAR* OldTruePath = File_ResolveTruePath(SourceTruePath, SourceCopyPath, NULL);
+ if (OldTruePath)
+ SourceTruePath2 = OldTruePath;
+
+ RtlInitUnicodeString(&objname, SourceTruePath2);
status2 = __sys_NtQueryFullAttributesFile(&objattrs, &open_info);
+
+ if (File_Delete_v2) {
+
+ BOOLEAN TrueExists = FALSE;
+ BOOLEAN IsDirectroy;
+
+ if (NT_SUCCESS(status2)) {
+
+ //
+ // if this file exist in the true path mark it as deleted,
+ // directories are handled by File_SetRelocation
+ //
+
+ TrueExists = TRUE;
+ IsDirectroy = (open_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+
+ if (!IsDirectroy)
+ File_MarkDeleted_v2(SourceTruePath);
+ }
+ else {
+
+ //
+ // if it does nto exist check if it was a directory, it may be a boxed directroy
+ // which is a relocation target in which case we will need to update the relocation data
+ //
+
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_BASIC_INFORMATION info3;
+
+ status2 = __sys_NtQueryInformationFile(
+ FileHandle, &IoStatusBlock, &info3,
+ sizeof(FILE_BASIC_INFORMATION), FileBasicInformation);
+
+ IsDirectroy = (info3.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ }
+
+ //
+ // if this is a directory and if so update/create the appropriate remapping
+ //
+
+ if (IsDirectroy) {
+
+ File_SetRelocation(SourceTruePath, TargetTruePath, TrueExists);
+ }
+ }
+ else
if (NT_SUCCESS(status2)) {
+ HANDLE handle2;
+
//
// mark deleted only if there is a corresponding file
// outside the sandbox
@@ -6840,8 +7082,10 @@ _FX ULONG SbieDll_GetHandlePath(
if (Dll_BoxName && // sandboxed process
IsBoxedPath && *IsBoxedPath) {
- if (File_Snapshot != NULL)
- File_FindSnapshotPath(&CopyPath);
+ if (File_Snapshot != NULL) {
+ WCHAR* TmplName = File_FindSnapshotPath(CopyPath);
+ if (TmplName) CopyPath = TmplName;
+ }
src = CopyPath;
}
diff --git a/Sandboxie/core/dll/file_copy.c b/Sandboxie/core/dll/file_copy.c
index c6173790..7102baef 100644
--- a/Sandboxie/core/dll/file_copy.c
+++ b/Sandboxie/core/dll/file_copy.c
@@ -278,6 +278,7 @@ _FX NTSTATUS File_MigrateFile(
if (status == STATUS_SHARING_VIOLATION) {
+ if (!Dll_CompartmentMode) // NoDriverAssist
status = SbieApi_OpenFile(&TrueHandle, TruePath);
if (!NT_SUCCESS(status)) {
diff --git a/Sandboxie/core/dll/file_del.c b/Sandboxie/core/dll/file_del.c
new file mode 100644
index 00000000..1feaa362
--- /dev/null
+++ b/Sandboxie/core/dll/file_del.c
@@ -0,0 +1,763 @@
+/*
+ * Copyright 2022 David Xanatos, xanasoft.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+//---------------------------------------------------------------------------
+// File (Delete)
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#define FILE_PATH_FILE_NAME L"FilePaths.dat"
+
+// path flages, saved to file
+#define FILE_DELETED_FLAG 0x0001
+#define FILE_RELOCATION_FLAG 0x0002
+
+// internal volatile status flags
+#define FILE_PATH_DELETED_FLAG 0x00010000
+#define FILE_PATH_RELOCATED_FLAG 0x00020000
+#define FILE_CHILDREN_DELETED_FLAG 0x00040000
+
+#define FILE_DELETED_MASK (FILE_DELETED_FLAG | FILE_PATH_DELETED_FLAG)
+#define FILE_RELOCATED_MASK (FILE_RELOCATION_FLAG | FILE_PATH_RELOCATED_FLAG)
+
+#define FILE_IS_DELETED(x) ((x & FILE_DELETED_FLAG) != 0)
+#define FILE_PATH_DELETED(x) ((x & FILE_DELETED_MASK) != 0)
+#define FILE_PARENT_DELETED(x) ((x & FILE_PATH_DELETED_FLAG) != 0)
+#define FILE_PATH_RELOCATED(x) ((x & FILE_RELOCATED_MASK) != 0)
+
+//---------------------------------------------------------------------------
+// Structures and Types
+//---------------------------------------------------------------------------
+
+typedef struct _PATH_NODE {
+ LIST_ELEM list_elem;
+ LIST items;
+ ULONG flags;
+ WCHAR* relocation;
+ ULONG name_len;
+ WCHAR name[1];
+} PATH_NODE;
+
+
+//---------------------------------------------------------------------------
+// Variables
+//---------------------------------------------------------------------------
+
+
+static LIST File_PathRoot;
+static CRITICAL_SECTION *File_PathRoot_CritSec = NULL;
+
+static HANDLE File_BoxRootWatcher = NULL;
+
+//---------------------------------------------------------------------------
+// Functions
+//---------------------------------------------------------------------------
+
+static ULONG File_GetPathFlags(const WCHAR* Path, WCHAR** pRelocation);
+static BOOLEAN File_SavePathTree();
+static BOOLEAN File_LoadPathTree();
+static VOID File_RefreshPathTree();
+static BOOLEAN File_InitDelete_v2();
+
+static NTSTATUS File_MarkDeleted_v2(const WCHAR *TruePath);
+static ULONG File_IsDeleted_v2(const WCHAR* TruePath);
+static BOOLEAN File_HasDeleted_v2(const WCHAR* TruePath);
+static WCHAR* File_GetRelocation(const WCHAR* TruePath);
+static NTSTATUS File_SetRelocation(const WCHAR *OldTruePath, const WCHAR *NewTruePath, BOOLEAN TrueExists);
+
+//---------------------------------------------------------------------------
+// File_ClearPathBranche
+//---------------------------------------------------------------------------
+
+
+_FX VOID File_ClearPathBranche_internal(LIST* parent)
+{
+ PATH_NODE* child = List_Head(parent);
+ while (child) {
+
+ PATH_NODE* next_child = List_Next(child);
+
+ File_ClearPathBranche_internal(&child->items);
+
+ List_Remove(parent, child);
+ if(child->relocation) Dll_Free(child->relocation);
+ Dll_Free(child);
+
+ child = next_child;
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// File_GetPathNode_internal
+//---------------------------------------------------------------------------
+
+
+_FX PATH_NODE* File_GetPathNode_internal(LIST* parent, const WCHAR* name, ULONG name_len, BOOLEAN can_add)
+{
+ PATH_NODE* child;
+
+ child = List_Head(parent);
+ while (child) {
+
+ if (child->name_len == name_len && _wcsnicmp(child->name, name, name_len) == 0)
+ break;
+
+ child = List_Next(child);
+ }
+
+ if (!child && can_add) {
+
+ child = Dll_Alloc(sizeof(PATH_NODE) + name_len*sizeof(WCHAR));
+ memzero(child, sizeof(PATH_NODE));
+ //List_Init(child->items); // done by memzero
+ child->name_len = name_len;
+ wmemcpy(child->name, name, name_len);
+ child->name[name_len] = L'\0';
+
+ List_Insert_After(parent, NULL, child);
+ }
+
+ return child;
+}
+
+
+//---------------------------------------------------------------------------
+// File_FindPathBranche_internal
+//---------------------------------------------------------------------------
+
+
+_FX PATH_NODE* File_FindPathBranche_internal(LIST* Root, const WCHAR* Path, LIST** pParent, BOOLEAN can_add)
+{
+ LIST* Parent = Root;
+ PATH_NODE* Node;
+ const WCHAR* next;
+ for (const WCHAR* ptr = Path; *ptr; ptr = next + 1) {
+ next = wcschr(ptr, L'\\');
+ if (ptr == next) // handle initial \ as well as \\ or \\\ etc cases
+ continue;
+ if(!next) next = wcschr(ptr, L'\0'); // last
+
+ Node = File_GetPathNode_internal(Parent, ptr, (ULONG)(next - ptr), can_add);
+ if (!Node)
+ return NULL;
+
+ if (*next == L'\0') {
+ if (pParent) *pParent = Parent;
+ return Node;
+ }
+ Parent = &Node->items;
+ }
+
+ return NULL;
+}
+
+
+//---------------------------------------------------------------------------
+// File_SetPathFlags_internal
+//---------------------------------------------------------------------------
+
+
+_FX VOID File_SetPathFlags_internal(LIST* Root, const WCHAR* Path, ULONG setFlags, ULONG clrFlags, const WCHAR* Relocation)
+{
+ PATH_NODE* Parent = Root;
+ PATH_NODE* Node;
+ const WCHAR* next;
+ for (const WCHAR* ptr = Path; *ptr; ptr = next + 1) {
+ next = wcschr(ptr, L'\\');
+ if (ptr == next) // handle initial \ as well as \\ or \\\ etc cases
+ continue;
+ if(!next) next = wcschr(ptr, L'\0'); // last
+
+ Node = File_GetPathNode_internal(Parent, ptr, (ULONG)(next - ptr), TRUE);
+
+ if (*next == L'\0') { // set flag always on the last element only
+
+ Node->flags |= setFlags;
+ Node->flags &= ~clrFlags;
+
+ if ((clrFlags & FILE_RELOCATION_FLAG) != 0 || (setFlags & FILE_RELOCATION_FLAG) != 0) {
+ if (Node->relocation) {
+ Dll_Free(Node->relocation);
+ Node->relocation = NULL;
+ }
+ }
+ if ((setFlags & FILE_RELOCATION_FLAG) != 0 && Relocation != NULL) {
+ if (Relocation && wcslen(Relocation) > 0) {
+ Node->relocation = Dll_Alloc((wcslen(Relocation) + 1) * sizeof(WCHAR));
+ wcscpy(Node->relocation, Relocation);
+ }
+ }
+
+ break;
+ }
+ Parent = &Node->items;
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// File_GetPathFlags_internal
+//---------------------------------------------------------------------------
+
+
+_FX ULONG File_GetPathFlags_internal(LIST* Root, const WCHAR* Path, WCHAR** pRelocation, BOOLEAN CheckChildren)
+{
+ ULONG Flags = 0;
+ const WCHAR* Relocation = NULL;
+ const WCHAR* SubPath = NULL;
+
+ LIST* Parent = Root;
+ PATH_NODE* Node;
+ PATH_NODE* child;
+ const WCHAR* next;
+ for (const WCHAR* ptr = Path; *ptr; ptr = next + 1) {
+ next = wcschr(ptr, L'\\');
+ if (ptr == next) // handle initial \ as well as \\ or \\\ etc cases
+ continue;
+ if(!next) next = wcschr(ptr, L'\0'); // last
+
+ Node = File_GetPathNode_internal(Parent, ptr, (ULONG)(next - ptr), FALSE);
+ if (!Node)
+ break;
+
+ //
+ // we return the last relocation target
+ //
+
+ if ((Node->flags & FILE_RELOCATION_FLAG) != 0) {
+ Relocation = Node->relocation;
+ SubPath = next;
+ }
+
+
+ if (*next == L'\0') { // last path segment
+
+ if ((Node->flags & FILE_RELOCATION_FLAG) != 0)
+ Flags |= FILE_RELOCATION_FLAG;
+ if ((Node->flags & FILE_DELETED_FLAG) != 0)
+ Flags |= FILE_DELETED_FLAG; // flag set for the path
+
+ if (CheckChildren) {
+ child = List_Head(&Node->items);
+ while (child) {
+ if ((child->flags & Flags) == Flags) {
+ Flags |= FILE_CHILDREN_DELETED_FLAG; // path set for children
+ break;
+ }
+ child = List_Next(child);
+ }
+ }
+
+ break;
+ }
+
+ //
+ // if we encounter a relocation previosue deletions on the path will be reset
+ // relocations are only allowed to exist for not deleted paths
+ //
+
+ if ((Node->flags & FILE_RELOCATION_FLAG) != 0) {
+ Flags = 0; // reset
+ Flags |= FILE_PATH_RELOCATED_FLAG;
+ }
+ else if ((Node->flags & FILE_DELETED_FLAG) != 0)
+ Flags |= FILE_PATH_DELETED_FLAG; // flag set for ancestor
+
+ Parent = &Node->items;
+ }
+
+ if (Relocation && pRelocation) {
+
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ *pRelocation = Dll_GetTlsNameBuffer(TlsData, MOVE_NAME_BUFFER, (wcslen(Relocation) + wcslen(SubPath) + 16) * sizeof(WCHAR)); // +16 some room for changes
+ wcscpy(*pRelocation, Relocation);
+ wcscat(*pRelocation, SubPath);
+ }
+
+ return Flags;
+}
+
+
+//---------------------------------------------------------------------------
+// File_GetPathFlags
+//---------------------------------------------------------------------------
+
+
+_FX ULONG File_GetPathFlags(const WCHAR* Path, WCHAR** pRelocation)
+{
+ ULONG Flags;
+
+ File_RefreshPathTree();
+
+ EnterCriticalSection(File_PathRoot_CritSec);
+
+ Flags = File_GetPathFlags_internal(&File_PathRoot, Path, pRelocation, TRUE);
+
+ LeaveCriticalSection(File_PathRoot_CritSec);
+
+ return Flags;
+}
+
+
+//---------------------------------------------------------------------------
+// File_SavePathNode_internal
+//---------------------------------------------------------------------------
+
+
+_FX VOID File_SavePathNode_internal(HANDLE hPathsFile, LIST* parent, WCHAR* Path, ULONG Length, ULONG SetFlags)
+{
+ const WCHAR CrLf[] = L"\r\n";
+ WCHAR FlagStr[16] = L"|";
+
+ // append L"\\"
+ Path[Length++] = L'\\'; //Path[Length] = L'0';
+ WCHAR* PathBase = Path + Length;
+
+ PATH_NODE* child;
+ child = List_Head(parent);
+ while (child) {
+
+ wmemcpy(PathBase, child->name, child->name_len + 1);
+ ULONG Path_Len = Length + child->name_len;
+
+ //
+ // don't write down flags that were already set for the parent,
+ // unless we have a relocation, that resets everything
+ //
+
+ if ((child->flags & FILE_RELOCATION_FLAG) != 0)
+ SetFlags = 0;
+
+ if ((child->flags & ~SetFlags) != 0 || child->relocation != NULL) {
+
+ // write the path
+ WriteFile(hPathsFile, Path, Path_Len * sizeof(WCHAR), NULL, NULL);
+
+ // write the flags
+ _ultow(child->flags, FlagStr + 1, 16);
+ WriteFile(hPathsFile, FlagStr, wcslen(FlagStr) * sizeof(WCHAR), NULL, NULL);
+
+ // write the relocation
+ if (child->relocation != NULL) {
+ WriteFile(hPathsFile, FlagStr, sizeof(WCHAR), NULL, NULL); // write |
+ WriteFile(hPathsFile, child->relocation, wcslen(child->relocation) * sizeof(WCHAR), NULL, NULL);
+ }
+
+ // write line ending
+ WriteFile(hPathsFile, CrLf, sizeof(CrLf) - sizeof(WCHAR), NULL, NULL);
+ }
+
+ File_SavePathNode_internal(hPathsFile, &child->items, Path, Path_Len, SetFlags | child->flags);
+
+ child = List_Next(child);
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// File_SavePathTree_internal
+//---------------------------------------------------------------------------
+
+
+_FX VOID File_SavePathTree_internal(LIST* Root, const WCHAR* name)
+{
+ WCHAR PathsFile[MAX_PATH] = { 0 };
+ wcscpy(PathsFile, Dll_BoxFilePath);
+ wcscat(PathsFile, L"\\");
+ wcscat(PathsFile, name);
+ SbieDll_TranslateNtToDosPath(PathsFile);
+
+ HANDLE hPathsFile;
+ hPathsFile = CreateFile(PathsFile, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hPathsFile == INVALID_HANDLE_VALUE)
+ return;
+
+ WCHAR* Path = (WCHAR *)Dll_Alloc((0x7FFF + 1)*sizeof(WCHAR)); // max nt path
+
+ File_SavePathNode_internal(hPathsFile, Root, Path, 0, 0);
+
+ Dll_Free(Path);
+
+ CloseHandle(hPathsFile);
+}
+
+
+//---------------------------------------------------------------------------
+// File_SavePathTree
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN File_SavePathTree()
+{
+ EnterCriticalSection(File_PathRoot_CritSec);
+
+ File_SavePathTree_internal(&File_PathRoot, FILE_PATH_FILE_NAME);
+
+ LeaveCriticalSection(File_PathRoot_CritSec);
+
+ return TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+// File_LoadPathTree_internal
+//---------------------------------------------------------------------------
+
+
+_FX VOID File_LoadPathTree_internal(LIST* Root, const WCHAR* name)
+{
+ WCHAR PathsFile[MAX_PATH] = { 0 };
+ wcscpy(PathsFile, Dll_BoxFilePath);
+ wcscat(PathsFile, L"\\");
+ wcscat(PathsFile, name);
+ SbieDll_TranslateNtToDosPath(PathsFile);
+
+ HANDLE hPathsFile;
+ hPathsFile = CreateFile(PathsFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hPathsFile == INVALID_HANDLE_VALUE)
+ return;
+
+ File_ClearPathBranche_internal(Root);
+
+ LARGE_INTEGER fileSize;
+ GetFileSizeEx(hPathsFile, &fileSize);
+
+ WCHAR* Buffer = (WCHAR *)Dll_Alloc((ULONG)fileSize.QuadPart + 128);
+ DWORD bytesRead;
+ ReadFile(hPathsFile, Buffer, (DWORD)fileSize.QuadPart, &bytesRead, NULL);
+ Buffer[bytesRead/sizeof(WCHAR)] = L'\0';
+
+ WCHAR* Next = Buffer;
+ while (*Next) {
+ WCHAR* Line = Next;
+ WCHAR* End = wcschr(Line, L'\n');
+ if (End == NULL) {
+ End = wcschr(Line, L'\0');
+ Next = End;
+ } else
+ Next = End + 1;
+ LONG LineLen = (LONG)(End - Line);
+ if (LineLen > 1 && Line[LineLen - 1] == L'\r')
+ LineLen -= 1;
+
+ WCHAR savechar = Line[LineLen];
+ Line[LineLen] = L'\0';
+
+ WCHAR* Sep = wcschr(Line, L'|');
+ if (!Sep || Sep > Next) continue; // invalid line, flags field missing
+ *Sep = L'\0';
+
+ WCHAR* endptr;
+ ULONG Flags = wcstoul(Sep + 1, &endptr, 16);
+ if (endptr && *endptr == L'|') endptr++;
+ else endptr = NULL;
+
+ File_SetPathFlags_internal(Root, Line, Flags, 0, endptr);
+
+ *Sep = L'|';
+ Line[LineLen] = savechar;
+ }
+
+ Dll_Free(Buffer);
+
+ CloseHandle(hPathsFile);
+}
+
+
+//---------------------------------------------------------------------------
+// File_LoadPathTree
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN File_LoadPathTree()
+{
+ EnterCriticalSection(File_PathRoot_CritSec);
+
+ File_LoadPathTree_internal(&File_PathRoot, FILE_PATH_FILE_NAME);
+
+ LeaveCriticalSection(File_PathRoot_CritSec);
+
+ return TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+// File_RefreshPathTree
+//---------------------------------------------------------------------------
+
+
+_FX VOID File_RefreshPathTree()
+{
+ if (!File_BoxRootWatcher)
+ return;
+
+ if (WaitForSingleObject(File_BoxRootWatcher, 0) == WAIT_OBJECT_0) {
+
+ //
+ // somethign changed, reload the path tree
+ //
+
+ File_LoadPathTree();
+ }
+
+ FindNextChangeNotification(File_BoxRootWatcher); // rearm the watcher
+}
+
+
+//---------------------------------------------------------------------------
+// File_InitDelete_v2
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN File_InitDelete_v2()
+{
+ List_Init(&File_PathRoot);
+
+ File_PathRoot_CritSec = Dll_Alloc(sizeof(CRITICAL_SECTION));
+ InitializeCriticalSectionAndSpinCount(File_PathRoot_CritSec, 1000);
+
+ File_LoadPathTree();
+
+//#ifdef WITH_DEBUG
+// File_SavePathTree();
+//#endif
+
+ WCHAR BoxFilePath[MAX_PATH] = { 0 };
+ wcscpy(BoxFilePath, Dll_BoxFilePath);
+ SbieDll_TranslateNtToDosPath(BoxFilePath);
+
+ File_BoxRootWatcher = FindFirstChangeNotification(BoxFilePath, FALSE, FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE);
+
+ return TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+// File_MarkDeleted_internal
+//---------------------------------------------------------------------------
+
+
+_FX VOID File_MarkDeleted_internal(LIST* Root, const WCHAR* Path)
+{
+ EnterCriticalSection(File_PathRoot_CritSec);
+
+ // 1. remove deleted branche
+
+ LIST* Parent = NULL;
+ PATH_NODE* Node = File_FindPathBranche_internal(Root, Path, &Parent, FALSE);
+ if (Node) {
+ List_Remove(Parent, Node);
+
+ File_ClearPathBranche_internal(&Node->items);
+ if (Node->relocation) Dll_Free(Node->relocation);
+ Dll_Free(Node);
+ }
+
+ // 2. set deleted flag
+
+ File_SetPathFlags_internal(Root, Path, FILE_DELETED_FLAG, 0, NULL);
+
+ // done
+
+ LeaveCriticalSection(File_PathRoot_CritSec);
+
+ File_SavePathTree();
+}
+
+
+//---------------------------------------------------------------------------
+// File_MarkDeleted_v2
+//---------------------------------------------------------------------------
+
+
+_FX NTSTATUS File_MarkDeleted_v2(const WCHAR* TruePath)
+{
+ //
+ // add a file or directory to the deleted list
+ //
+
+ EnterCriticalSection(File_PathRoot_CritSec);
+
+ File_MarkDeleted_internal(&File_PathRoot, TruePath);
+
+ LeaveCriticalSection(File_PathRoot_CritSec);
+
+ File_SavePathTree();
+
+ return STATUS_SUCCESS;
+}
+
+
+//---------------------------------------------------------------------------
+// File_IsDeleted_v2
+//---------------------------------------------------------------------------
+
+
+_FX ULONG File_IsDeleted_v2(const WCHAR* TruePath)
+{
+ //
+ // check if the file or one of its parent directories is listed as deleted
+ // use the dedicated test method to properly take into account relocations
+ //
+
+ ULONG Flags = File_GetPathFlags(TruePath, NULL);
+
+ return (Flags & FILE_DELETED_MASK);
+}
+
+
+//---------------------------------------------------------------------------
+// File_HasDeleted_v2
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN File_HasDeleted_v2(const WCHAR* TruePath)
+{
+ //
+ // Check if this folder has deleted children
+ //
+
+ ULONG Flags = File_GetPathFlags(TruePath, NULL);
+
+ return (Flags & FILE_CHILDREN_DELETED_FLAG) != 0;
+}
+
+
+//---------------------------------------------------------------------------
+// File_SetRelocation_internal
+//---------------------------------------------------------------------------
+
+
+_FX VOID File_SetRelocation_internal(LIST* Root, const WCHAR *OldTruePath, const WCHAR *NewTruePath, BOOLEAN TrueExists)
+{
+ // 1. separate branche from OldTruePath
+
+ LIST* Parent = NULL;
+ PATH_NODE* Node = File_FindPathBranche_internal(Root, OldTruePath, &Parent, FALSE);
+ //if(Node)
+ // List_Remove(Parent, Node); // leave node in it may have a delete flag
+
+ // 2. check if old path has a relocation
+
+ BOOLEAN HasRelocation = FALSE;
+ if (Node && (Node->flags & FILE_RELOCATION_FLAG) != 0) {
+ Node->flags &= ~FILE_RELOCATION_FLAG;
+ if (Node->relocation) {
+ HasRelocation = TRUE;
+ OldTruePath = Node->relocation; // update relocation to oritinal true target
+ }
+ }
+
+ // 3. add true delete entry OldTruePath
+
+ File_SetPathFlags_internal(Root, OldTruePath, FILE_DELETED_FLAG, 0, NULL);
+
+ // 4. set redirection NewTruePath -> OldTruePath
+
+ if (TrueExists || HasRelocation || (Node && Node->items.count > 0)) {
+
+ PATH_NODE* NewNode = File_FindPathBranche_internal(Root, NewTruePath, NULL, TRUE);
+
+ // OldTruePath may have a relocated parent, if so unwrap it
+ if (!HasRelocation) {
+ WCHAR* OldOldTruePath = NULL;
+ File_GetPathFlags_internal(&File_PathRoot, OldTruePath, &OldOldTruePath, TRUE);
+ if (OldOldTruePath) OldTruePath = OldOldTruePath;
+ }
+
+ if (TrueExists || HasRelocation) {
+ NewNode->flags |= FILE_RELOCATION_FLAG;
+ NewNode->relocation = Dll_Alloc((wcslen(OldTruePath) + 1) * sizeof(WCHAR));
+ wcscpy(NewNode->relocation, OldTruePath);
+ }
+
+ // 5. reatach branche to NewTruePath
+
+ if (Node) {
+ PATH_NODE* child = List_Head(&Node->items);
+ while (child) {
+
+ PATH_NODE* next_child = List_Next(child);
+
+ List_Remove(&Node->items, child);
+
+ List_Insert_After(&NewNode->items, NULL, child);
+
+ child = next_child;
+ }
+ }
+ }
+
+ // 6. clean up
+
+ //if (Node) {
+ if (HasRelocation) {
+ //if (Node->relocation)
+ Dll_Free(Node->relocation);
+ Node->relocation = NULL;
+ //Dll_Free(Node);
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// File_SetRelocation
+//---------------------------------------------------------------------------
+
+
+_FX NTSTATUS File_SetRelocation(const WCHAR* OldTruePath, const WCHAR* NewTruePath, BOOLEAN TrueExists)
+{
+ //
+ // List a mapping for the new location
+ //
+
+ EnterCriticalSection(File_PathRoot_CritSec);
+
+ File_SetRelocation_internal(&File_PathRoot, OldTruePath, NewTruePath, TrueExists);
+
+ LeaveCriticalSection(File_PathRoot_CritSec);
+
+ File_SavePathTree();
+
+ return STATUS_SUCCESS;
+}
+
+
+//---------------------------------------------------------------------------
+// File_GetRelocation
+//---------------------------------------------------------------------------
+
+
+_FX WCHAR* File_GetRelocation(const WCHAR *TruePath)
+{
+ //
+ // Get redirection location, only if its the actual path and not a parent
+ //
+
+ WCHAR* OldTruePath = NULL;
+ ULONG Flags = File_GetPathFlags(TruePath, &OldTruePath);
+ if (FILE_PATH_RELOCATED(Flags))
+ return OldTruePath;
+
+ return NULL;
+}
+
diff --git a/Sandboxie/core/dll/file_dir.c b/Sandboxie/core/dll/file_dir.c
index 4897f79f..30e98793 100644
--- a/Sandboxie/core/dll/file_dir.c
+++ b/Sandboxie/core/dll/file_dir.c
@@ -44,6 +44,7 @@ typedef struct _FILE_MERGE_CACHE_FILE {
typedef struct _FILE_MERGE_FILE {
HANDLE handle;
+ FILE_SNAPSHOT* shapshot;
FILE_ID_BOTH_DIR_INFORMATION *info;
ULONG info_len;
WCHAR *name;
@@ -94,14 +95,6 @@ typedef struct _FILE_FS_DEVICE_INFORMATION {
ULONG Characteristics;
} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION;
-#define MAX_CLOSE_HANDLERS 4
-
-typedef struct _FILE_ON_CLOSE {
-
- BOOLEAN DeleteOnClose;
- P_CloseHandler CloseHandlers[MAX_CLOSE_HANDLERS];
-
-} FILE_ON_CLOSE;
//---------------------------------------------------------------------------
// Functions
@@ -157,7 +150,7 @@ static NTSTATUS File_MergeDummy(
static void File_MergeFree(FILE_MERGE *merge);
static NTSTATUS File_GetMergedInformation(
- FILE_MERGE *merge,
+ FILE_MERGE *merge, WCHAR *TruePath, WCHAR *CopyPath,
IO_STATUS_BLOCK *IoStatusBlock,
void *FileInformation,
ULONG Length,
@@ -178,14 +171,6 @@ static NTSTATUS File_DeleteDirectory(
static NTSTATUS File_MarkChildrenDeleted(const WCHAR *ParentTruePath);
-static void File_InitRecoverList(
- const WCHAR *setting, LIST *list, BOOLEAN MustBeValidPath,
- WCHAR *buf, ULONG buf_len);
-
-static void File_NotifyRecover(HANDLE FileHandle);
-
-static BOOLEAN File_IsRecoverable(const WCHAR *TruePath);
-
static ULONG File_RtlGetCurrentDirectory_U(ULONG buf_len, WCHAR *buf_ptr);
static NTSTATUS File_RtlSetCurrentDirectory_U(UNICODE_STRING *PathName);
@@ -207,17 +192,6 @@ static NTSTATUS File_NtQueryVolumeInformationFile(
ULONG Length,
ULONG FsInformationClass);
-static void File_DoAutoRecover_2(BOOLEAN force, ULONG ticks);
-
-static ULONG File_DoAutoRecover_3(
- const WCHAR *PathToFind, WCHAR *PathBuf1024,
- SYSTEM_HANDLE_INFORMATION *info, FILE_GET_ALL_HANDLES_RPL *rpl,
- UCHAR *FileObjectTypeNumber);
-
-static ULONG File_DoAutoRecover_4(
- const WCHAR *PathToFind, WCHAR *PathBuf1024,
- HANDLE FileHandle, UCHAR ObjectTypeNumber, UCHAR *FileObjectTypeNumber);
-
NTSTATUS File_NtCloseImpl(HANDLE FileHandle);
VOID File_NtCloseDir(HANDLE FileHandle);
@@ -227,12 +201,6 @@ VOID File_NtCloseDir(HANDLE FileHandle);
//---------------------------------------------------------------------------
-static LIST File_RecoverFolders;
-static LIST File_RecoverIgnores;
-
-static LIST File_RecPaths;
-static CRITICAL_SECTION File_RecHandles_CritSec;
-
static CRITICAL_SECTION File_CurDir_CritSec;
static WCHAR *File_CurDir_LastInput = NULL;
static WCHAR *File_CurDir_LastOutput = NULL;
@@ -240,10 +208,7 @@ static WCHAR *File_CurDir_LastOutput = NULL;
static LIST File_DirHandles;
static CRITICAL_SECTION File_DirHandles_CritSec;
-static HASH_MAP File_HandleOnClose;
-static CRITICAL_SECTION File_HandleOnClose_CritSec;
-static BOOLEAN File_MsoDllLoaded = FALSE;
//---------------------------------------------------------------------------
@@ -418,7 +383,7 @@ _FX NTSTATUS File_NtQueryDirectoryFile(
merge_lock = TRUE;
status = File_GetMergedInformation(
- merge, IoStatusBlock,
+ merge, TruePath, CopyPath, IoStatusBlock,
FileInformation, Length, FileInformationClass, ReturnSingleEntry);
if (merge->first_request) {
@@ -519,7 +484,7 @@ _FX NTSTATUS File_Merge(
} else {
- File_UnRegisterCloseHandler(merge->handle, File_NtCloseDir);
+ Handle_UnRegisterCloseHandler(merge->handle, File_NtCloseDir);
List_Remove(&File_DirHandles, merge);
File_MergeFree(merge);
}
@@ -573,7 +538,7 @@ _FX NTSTATUS File_Merge(
}
List_Insert_After(&File_DirHandles, NULL, merge);
- File_RegisterCloseHandler(merge->handle, File_NtCloseDir);
+ Handle_RegisterCloseHandler(merge->handle, File_NtCloseDir);
}
//
@@ -637,8 +602,14 @@ _FX NTSTATUS File_OpenForMerge(
WCHAR *ptr;
// BOOLEAN TruePathIsRoot;
BOOLEAN TruePathDeleted = FALSE; // indicates that one of the parent snapshots deleted the true directory
+ WCHAR* OriginalPath = NULL;
+ ULONG TruePathFlags = 0;
BOOLEAN NoCopyPath = FALSE;
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ Dll_PushTlsNameBuffer(TlsData);
+
InitializeObjectAttributes(
&objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
@@ -646,8 +617,27 @@ _FX NTSTATUS File_OpenForMerge(
// open the copy file
//
- if (File_CheckDeletedParent(CopyPath))
- return STATUS_OBJECT_PATH_NOT_FOUND;
+ if (File_Delete_v2) {
+
+ //
+ // test if the path is deleted and find the oldest snapshot with a relocation,
+ // or
+ //
+
+ WCHAR* OldTruePath = File_ResolveTruePath(TruePath, NULL, &TruePathFlags);
+ if (FILE_PATH_DELETED(TruePathFlags))
+ TruePathDeleted = TRUE;
+ else if (OldTruePath) {
+ OriginalPath = TruePath;
+ TruePath = OldTruePath;
+ }
+ }
+ else {
+ if (File_CheckDeletedParent(CopyPath)) {
+ status = STATUS_OBJECT_PATH_NOT_FOUND;
+ goto finish;
+ }
+ }
RtlInitUnicodeString(&objname, CopyPath);
@@ -678,6 +668,7 @@ _FX NTSTATUS File_OpenForMerge(
if (NT_SUCCESS(status)) {
+ // if (!File_Delete_v2 &&
if (IS_DELETE_MARK(&info.basic.CreationTime)) {
status = STATUS_OBJECT_NAME_NOT_FOUND;
@@ -694,10 +685,10 @@ _FX NTSTATUS File_OpenForMerge(
__sys_NtClose(merge->files[0].handle);
merge->files[0].handle = NULL;
- return status;
+ goto finish;
}
- //
+ //
// copy file passed all checks; indicate it is ready for use
//
@@ -719,7 +710,7 @@ _FX NTSTATUS File_OpenForMerge(
NoCopyPath = TRUE;
}
else
- return status;
+ goto finish;
}
//
@@ -728,6 +719,8 @@ _FX NTSTATUS File_OpenForMerge(
if (File_Snapshot != NULL)
{
+ WCHAR* TempPath = TruePath;
+
for (FILE_SNAPSHOT* Cur_Snapshot = File_Snapshot; Cur_Snapshot != NULL; Cur_Snapshot = Cur_Snapshot->Parent)
{
WCHAR* TmplName = File_MakeSnapshotPath(Cur_Snapshot, CopyPath);
@@ -757,14 +750,13 @@ _FX NTSTATUS File_OpenForMerge(
// make sure it is a directory file
//
- // todo reduce redundant code, combine with the code for the copy_file
-
status = __sys_NtQueryInformationFile(
merge->files[merge->files_count].handle, &IoStatusBlock, &info,
sizeof(FILE_BASIC_INFORMATION), FileBasicInformation);
if (NT_SUCCESS(status)) {
+ // if (!File_Delete_v2 &&
if (IS_DELETE_MARK(&info.basic.CreationTime)) {
status = STATUS_OBJECT_NAME_NOT_FOUND;
@@ -786,7 +778,9 @@ _FX NTSTATUS File_OpenForMerge(
break; // dont look any further
}
- //
+ merge->files[merge->files_count].shapshot = Cur_Snapshot;
+
+ //
// copy file passed all checks; indicate it is ready for use
//
@@ -796,13 +790,46 @@ _FX NTSTATUS File_OpenForMerge(
merge->files_count++;
}
- else {
+ // else: ignore the error, proceed to next snapshot
- //
- // Ignroe errors here for now // todo
- //
+ //
+ // check if we have a relocation and update CopyPath for the next snapshot accordingly
+ // since we dont need opypath anyware anymore we can alter it
+ //
- }
+ if (File_Delete_v2) {
+
+ WCHAR* Relocation;
+ ULONG Flags = File_GetPathFlags_internal(&Cur_Snapshot->PathRoot, TempPath, &Relocation, TRUE);
+ if (FILE_PATH_DELETED(Flags))
+ break;
+
+ if (Relocation) {
+
+ if (!Cur_Snapshot->Parent)
+ break; // take a shortcut
+
+ TempPath = Dll_GetTlsNameBuffer(TlsData, TRUE_NAME_BUFFER, (wcslen(Relocation) + 1) * sizeof(WCHAR));
+ wcscpy(TempPath, Relocation);
+
+ //
+ // update the copy file name
+ //
+
+ Dll_PushTlsNameBuffer(TlsData);
+
+ WCHAR* TruePath2, *CopyPath2;
+ RtlInitUnicodeString(&objname, Relocation);
+ File_GetName(NULL, &objname, &TruePath2, &CopyPath2, NULL);
+
+ Dll_PopTlsNameBuffer(TlsData);
+
+ // note: pop leaves TruePath2 valid we can still use it
+
+ CopyPath = Dll_GetTlsNameBuffer(TlsData, COPY_NAME_BUFFER, (wcslen(CopyPath2) + 1) * sizeof(WCHAR));
+ wcscpy(CopyPath, CopyPath2);
+ }
+ }
}
}
@@ -811,11 +838,12 @@ _FX NTSTATUS File_OpenForMerge(
// and can let the system work directly on the true file
//
- if (merge->files_count == 0) {
+ if ((TruePathFlags & FILE_CHILDREN_DELETED_FLAG) == 0) // we ned to do full merge if children ar marked deleted
+ if (merge->files_count == 0) {
status = STATUS_BAD_INITIAL_PC;
- return status;
+ goto finish;
}
if (TruePathDeleted)
@@ -915,7 +943,7 @@ _FX NTSTATUS File_OpenForMerge(
if (status == STATUS_ACCESS_DENIED)
status = STATUS_BAD_INITIAL_PC;
- return status;
+ goto finish;
}
status = STATUS_SUCCESS;
@@ -1003,6 +1031,9 @@ skip_true_file:
}
}
+finish:
+ Dll_PopTlsNameBuffer(TlsData);
+
return status;
}
@@ -1517,7 +1548,7 @@ _FX void File_MergeFree(FILE_MERGE *merge)
_FX NTSTATUS File_GetMergedInformation(
- FILE_MERGE *merge,
+ FILE_MERGE *merge, WCHAR *TruePath, WCHAR *CopyPath,
IO_STATUS_BLOCK *IoStatusBlock,
void *FileInformation,
ULONG Length,
@@ -1531,6 +1562,8 @@ _FX NTSTATUS File_GetMergedInformation(
PVOID next_entry;
WCHAR *name_ptr;
ULONG len;
+ ULONG TruePathLen = wcslen(TruePath);
+ ULONG CopyPathLen = wcslen(CopyPath);
info_entry_length = 0;
if (FileInformationClass == FileDirectoryInformation)
@@ -1551,6 +1584,10 @@ _FX NTSTATUS File_GetMergedInformation(
if (info_entry_length > Length)
return STATUS_INFO_LENGTH_MISMATCH;
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ Dll_PushTlsNameBuffer(TlsData);
+
prev_entry = FileInformation;
next_entry = FileInformation;
@@ -1628,15 +1665,6 @@ _FX NTSTATUS File_GetMergedInformation(
best->have_entry = FALSE;
}
- // if the entry found was in the copy directory, then the file
- // may be marked deleted (see Filesys_Mark_File_Deleted for
- // details). if it is marked so, we pretend this entry does
- // not exist by fetching the following one
-
- if (ptr_info && (!merge->true_ptr || ptr_info != merge->true_ptr->info) &&
- IS_DELETE_MARK(&ptr_info->CreationTime))
- continue;
-
// if both directories are exhausted, reset the
// NextEntryOffset field of FILE_*_INFORMATION to
// indicate no more entries, and return status
@@ -1650,6 +1678,51 @@ _FX NTSTATUS File_GetMergedInformation(
break;
}
+ if (File_Delete_v2) {
+
+ if ((merge->true_ptr && ptr_info == merge->true_ptr->info) // is in true path
+ || ptr_info != merge->files[0].info) { // is in template
+
+ WCHAR* TruePath2 = Dll_GetTlsNameBuffer(TlsData, TRUE_NAME_BUFFER, ((TruePathLen + 1) * sizeof(WCHAR) + ptr_info->FileNameLength + sizeof(WCHAR)));
+ WCHAR* ptr = TruePath2;
+ wmemcpy(ptr, TruePath, TruePathLen);
+ ptr += TruePathLen;
+ if (ptr[-1] != L'\\') *ptr++ = L'\\';
+ wmemcpy(ptr, ptr_info->FileName, ptr_info->FileNameLength / sizeof(WCHAR));
+ ptr += ptr_info->FileNameLength / sizeof(WCHAR);
+ *ptr = L'\0';
+
+ WCHAR* CopyPath2 = Dll_GetTlsNameBuffer(TlsData, COPY_NAME_BUFFER, ((CopyPathLen + 1) * sizeof(WCHAR) + ptr_info->FileNameLength + sizeof(WCHAR)));
+ ptr = CopyPath2;
+ wmemcpy(ptr, CopyPath, CopyPathLen);
+ ptr += CopyPathLen;
+ if (ptr[-1] != L'\\') *ptr++ = L'\\';
+ wmemcpy(ptr, ptr_info->FileName, ptr_info->FileNameLength / sizeof(WCHAR));
+ ptr += ptr_info->FileNameLength / sizeof(WCHAR);
+ *ptr = L'\0';
+
+ //
+ // chekc if the file is listed as deleted
+ //
+
+ if (File_IsDeletedEx(TruePath2, CopyPath2, best->shapshot))
+ continue;
+
+ } //else // is in copy path - nothing to do
+ }
+ else {
+
+ // if the entry found was in the copy directory, then the file
+ // may be marked deleted (see Filesys_Mark_File_Deleted for
+ // details). if it is marked so, we pretend this entry does
+ // not exist by fetching the following one
+
+ if ((!merge->true_ptr || ptr_info != merge->true_ptr->info) &&
+ IS_DELETE_MARK(&ptr_info->CreationTime))
+ continue;
+ }
+
+
//
// make sure caller has enough room in output buffer for the
// entry. for the first entry in the buffer, it is ok to have
@@ -1675,9 +1748,8 @@ _FX NTSTATUS File_GetMergedInformation(
*(ULONG *)prev_entry = 0; // reset NextEntryOffset
if (next_entry == FileInformation)
- return STATUS_BUFFER_OVERFLOW;
- else
- break;
+ status = STATUS_BUFFER_OVERFLOW;
+ break;
}
//
@@ -1743,6 +1815,8 @@ _FX NTSTATUS File_GetMergedInformation(
IoStatusBlock->Information = // number of bytes written
(UCHAR *)next_entry - (UCHAR *)FileInformation;
+ Dll_PopTlsNameBuffer(TlsData);
+
return status;
}
@@ -2123,73 +2197,6 @@ _FX NTSTATUS File_NtClose(HANDLE FileHandle)
}
-//---------------------------------------------------------------------------
-// File_RegisterCloseHandler
-//---------------------------------------------------------------------------
-
-
-_FX BOOLEAN File_RegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler)
-{
- if (!FileHandle || FileHandle == (HANDLE)-1)
- return FALSE;
-
- ULONG i;
-
- EnterCriticalSection(&File_HandleOnClose_CritSec);
-
- FILE_ON_CLOSE* on_close = map_get(&File_HandleOnClose, FileHandle);
- if (!on_close) {
- on_close = map_insert(&File_HandleOnClose, FileHandle, NULL, sizeof(FILE_ON_CLOSE));
- }
-
- for (i = 0; i < MAX_CLOSE_HANDLERS; i++) {
- if (on_close->CloseHandlers[i] == CloseHandler)
- break; // already registered
- if (on_close->CloseHandlers[i] == NULL) {
- on_close->CloseHandlers[i] = CloseHandler; // set to empty slot
- break;
- }
- }
-
- LeaveCriticalSection(&File_HandleOnClose_CritSec);
-
- if (i == MAX_CLOSE_HANDLERS) {
- SbieApi_Log(2301, L"No free CloseHandlers slot available");
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-//---------------------------------------------------------------------------
-// File_UnRegisterCloseHandler
-//---------------------------------------------------------------------------
-
-
-_FX BOOLEAN File_UnRegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler)
-{
- ULONG i = MAX_CLOSE_HANDLERS;
-
- EnterCriticalSection(&File_HandleOnClose_CritSec);
-
- FILE_ON_CLOSE* on_close = map_get(&File_HandleOnClose, FileHandle);
- if (on_close) {
-
- for (i = 0; i < MAX_CLOSE_HANDLERS; i++) {
- if (on_close->CloseHandlers[i] == CloseHandler) {
- on_close->CloseHandlers[i] = NULL; // clear slot
- break;
- }
- }
- }
-
- LeaveCriticalSection(&File_HandleOnClose_CritSec);
-
- return i != MAX_CLOSE_HANDLERS;
-}
-
-
//---------------------------------------------------------------------------
// File_NtCloseImpl
//---------------------------------------------------------------------------
@@ -2202,7 +2209,6 @@ _FX NTSTATUS File_NtCloseImpl(HANDLE FileHandle)
NTSTATUS status;
ULONG i;
- BOOLEAN HasCloseHandlers = FALSE;
P_CloseHandler CloseHandlers[MAX_CLOSE_HANDLERS];
BOOLEAN DeleteOnClose = FALSE;
UNICODE_STRING uni;
@@ -2243,25 +2249,7 @@ _FX NTSTATUS File_NtCloseImpl(HANDLE FileHandle)
// and prepare the DeleteOnClose if its set
//
- EnterCriticalSection(&File_HandleOnClose_CritSec);
-
- FILE_ON_CLOSE* on_close = (FILE_ON_CLOSE*)map_get(&File_HandleOnClose, FileHandle);
- if (on_close) {
-
- HasCloseHandlers = TRUE;
- memcpy(CloseHandlers, on_close->CloseHandlers, sizeof(CloseHandlers));
- DeleteOnClose = on_close->DeleteOnClose;
- }
-
- map_remove(&File_HandleOnClose, FileHandle);
-
- LeaveCriticalSection(&File_HandleOnClose_CritSec);
-
- //
- // execute close handlers
- //
-
- if (HasCloseHandlers) {
+ if (Handle_FreeCloseHandler(FileHandle, &CloseHandlers[0], &DeleteOnClose)) {
for (i = 0; i < MAX_CLOSE_HANDLERS; i++) {
if(CloseHandlers[i] != NULL)
@@ -2360,7 +2348,7 @@ _FX VOID File_NtCloseDir(HANDLE FileHandle)
while (merge) {
FILE_MERGE *next = List_Next(merge);
if (merge->handle == FileHandle) {
- File_UnRegisterCloseHandler(merge->handle, File_NtCloseDir);
+ Handle_UnRegisterCloseHandler(merge->handle, File_NtCloseDir);
List_Remove(&File_DirHandles, merge);
File_MergeFree(merge);
}
@@ -2666,439 +2654,6 @@ _FX NTSTATUS File_MarkChildrenDeleted(const WCHAR *ParentTruePath)
}
-//---------------------------------------------------------------------------
-//
-// Immediate Recovery for Files
-//
-//---------------------------------------------------------------------------
-
-
-//---------------------------------------------------------------------------
-// Structures and Types
-//---------------------------------------------------------------------------
-
-
-typedef struct _FILE_RECOVER_FOLDER {
-
- LIST_ELEM list_elem;
- ULONG ticks; // for File_RecPaths
- ULONG path_len;
- WCHAR path[1];
-
-} FILE_RECOVER_FOLDER;
-
-
-//---------------------------------------------------------------------------
-// File_InitRecoverFolders
-//---------------------------------------------------------------------------
-
-
-_FX void File_InitRecoverFolders(void)
-{
- //
- // init list of recoverable file handles
- //
-
- List_Init(&File_RecoverFolders);
- List_Init(&File_RecoverIgnores);
-
- InitializeCriticalSectionAndSpinCount(&File_RecHandles_CritSec, 1000);
-
- List_Init(&File_RecPaths);
-
- //
- // init list of recover folders
- //
-
- if (SbieApi_QueryConfBool(NULL, L"AutoRecover", FALSE)) {
-
- ULONG buf_len = 4096 * sizeof(WCHAR);
- WCHAR *buf = Dll_AllocTemp(buf_len);
-
- File_InitRecoverList(
- L"RecoverFolder", &File_RecoverFolders, TRUE, buf, buf_len);
-
- File_InitRecoverList(
- L"AutoRecoverIgnore", &File_RecoverIgnores, FALSE, buf, buf_len);
-
- Dll_Free(buf);
- }
-}
-
-
-//---------------------------------------------------------------------------
-// File_InitRecoverList
-//---------------------------------------------------------------------------
-
-
-_FX void File_InitRecoverList(
- const WCHAR *setting, LIST *list, BOOLEAN MustBeValidPath,
- WCHAR *buf, ULONG buf_len)
-{
- UNICODE_STRING uni;
- WCHAR *TruePath, *CopyPath, *ReparsedPath;
- FILE_RECOVER_FOLDER *fold;
-
- ULONG index = 0;
- while (1) {
-
- NTSTATUS status = SbieApi_QueryConf(
- NULL, setting, index, buf, buf_len - 16 * sizeof(WCHAR));
- if (! NT_SUCCESS(status))
- break;
- ++index;
-
- RtlInitUnicodeString(&uni, buf);
- status = File_GetName(NULL, &uni, &TruePath, &CopyPath, NULL);
-
- ReparsedPath = NULL;
-
- if (NT_SUCCESS(status) && MustBeValidPath) {
-
- ReparsedPath = File_TranslateTempLinks(TruePath, FALSE);
- if (ReparsedPath)
- TruePath = ReparsedPath;
-
- } else if ((! NT_SUCCESS(status)) && (! MustBeValidPath)) {
-
- TruePath = buf;
- status = STATUS_SUCCESS;
- }
-
- if (NT_SUCCESS(status)) {
-
- ULONG len = wcslen(TruePath);
- if (len && TruePath[len - 1] == L'\\') {
- TruePath[len - 1] = L'\0';
- --len;
- }
- len = sizeof(FILE_RECOVER_FOLDER)
- + (len + 1) * sizeof(WCHAR);
- fold = Dll_Alloc(len);
-
- fold->ticks = 0; // not used
-
- wcscpy(fold->path, TruePath);
- fold->path_len = wcslen(fold->path);
-
- List_Insert_After(list, NULL, fold);
- }
-
- if (ReparsedPath)
- Dll_Free(ReparsedPath);
- }
-}
-
-
-//---------------------------------------------------------------------------
-// File_IsRecoverable
-//---------------------------------------------------------------------------
-
-
-_FX BOOLEAN File_IsRecoverable(
- const WCHAR *TruePath)
-{
- const WCHAR *save_TruePath;
- FILE_RECOVER_FOLDER *fold;
- const WCHAR *ptr;
- ULONG TruePath_len;
- ULONG PrefixLen;
- BOOLEAN ok;
-
- //
- // if we have a path that looks like
- // \Device\LanmanRedirector\;Q:000000000000b09f\server\share\f1.txt
- // \Device\Mup\;LanmanRedirector\;Q:000000000000b09f\server\share\f1.txt
- // then translate to
- // \Device\Mup\server\share\f1.txt
- // and test again. We do this because the SbieDrv records paths
- // in the \Device\Mup format. See SbieDrv::File_TranslateShares.
- //
-
- save_TruePath = TruePath;
-
- if (_wcsnicmp(TruePath, File_Redirector, File_RedirectorLen) == 0)
- PrefixLen = File_RedirectorLen;
- else if (_wcsnicmp(TruePath, File_DfsClientRedir, File_DfsClientRedirLen) == 0)
- PrefixLen = File_DfsClientRedirLen;
- else if (_wcsnicmp(TruePath, File_HgfsRedir, File_HgfsRedirLen) == 0)
- PrefixLen = File_HgfsRedirLen;
- else if (_wcsnicmp(TruePath, File_MupRedir, File_MupRedirLen) == 0)
- PrefixLen = File_MupRedirLen;
- else
- PrefixLen = 0;
-
- if (PrefixLen && TruePath[PrefixLen] == L';') {
-
- WCHAR *ptr = wcschr(TruePath + PrefixLen, L'\\');
- if (ptr && ptr[0] && ptr[1]) {
-
- ULONG len1 = wcslen(ptr + 1);
- ULONG len2 = (File_MupLen + len1 + 8) * sizeof(WCHAR);
- WCHAR *path2 = Dll_Alloc(len2);
- wmemcpy(path2, File_Mup, File_MupLen);
- wmemcpy(path2 + File_MupLen, ptr + 1, len1 + 1);
-
- TruePath = (const WCHAR *)path2;
- }
- }
-
- //
- // look for the TruePath in the list of RecoverFolder settings
- //
-
- ok = FALSE;
-
- fold = List_Head(&File_RecoverFolders);
- while (fold) {
-
- if (_wcsnicmp(fold->path, TruePath, fold->path_len) == 0) {
- ptr = TruePath + fold->path_len;
- if (*ptr == L'\\' || *ptr == L'\0') {
- ok = TRUE;
- break;
- }
- }
-
- fold = List_Next(fold);
- }
-
- if (! ok)
- goto finish;
-
- //
- // ignore files that begin with ~$ (Microsoft Office temp files)
- // or that don't have a file type extension (probably temp files)
- //
-
- if (File_MsoDllLoaded) {
-
- ptr = wcsrchr(TruePath, L'\\');
- if (ptr) {
- if (ptr[1] == L'~' && ptr[2] == L'$')
- ok = FALSE;
- else {
- ptr = wcschr(ptr, L'.');
- if (! ptr)
- ok = FALSE;
- }
- if (! ok)
- goto finish;
- }
- }
-
- //
- // look for TruePath in the list of AutoRecoverIgnore settings
- //
-
- TruePath_len = wcslen(TruePath);
-
- fold = List_Head(&File_RecoverIgnores);
- while (fold) {
-
- if (_wcsnicmp(fold->path, TruePath, fold->path_len) == 0) {
- ptr = TruePath + fold->path_len;
- if (*ptr == L'\\' || *ptr == L'\0') {
- ok = FALSE;
- break;
- }
- }
-
- if (TruePath_len >= fold->path_len) {
- ptr = TruePath + TruePath_len - fold->path_len;
- if (_wcsicmp(fold->path, ptr) == 0) {
- ok = FALSE;
- break;
- }
- }
-
- fold = List_Next(fold);
- }
-
- //
- // finish
- //
-
-finish:
-
- if (TruePath != save_TruePath)
- Dll_Free((WCHAR *)TruePath);
- return ok;
-}
-
-
-//---------------------------------------------------------------------------
-// File_RecordRecover
-//---------------------------------------------------------------------------
-
-
-_FX BOOLEAN File_RecordRecover(HANDLE FileHandle, const WCHAR *TruePath)
-{
- BOOLEAN IsRecoverable;
-
- IsRecoverable = File_IsRecoverable(TruePath);
-
- //
- // in a Chrome sandbox process, handles are opened by the broker,
- // so skip checking against the list of recorded file handles
- //
-
- // Note: this does not seam to be required anymore
-
- //if ((! IsRecoverable) && Dll_ChromeSandbox) {
- //
- // FILE_ACCESS_INFORMATION info;
- //
- // status = __sys_NtQueryInformationFile(
- // FileHandle, &IoStatusBlock, &info,
- // sizeof(FILE_ACCESS_INFORMATION), FileAccessInformation);
- //
- // if (NT_SUCCESS(status) && (info.AccessFlags & FILE_WRITE_DATA))
- // IsRecoverable = 2; //TRUE; // we still want to return false when called from File_NtCreateFileImpl
- // else
- // IsRecoverable = FALSE;
- //}
-
- if (IsRecoverable != FALSE)
- File_RegisterCloseHandler(FileHandle, File_NotifyRecover);
-
- return IsRecoverable == TRUE;
-}
-
-
-//---------------------------------------------------------------------------
-// File_DuplicateRecover
-//---------------------------------------------------------------------------
-
-
-_FX void File_DuplicateRecover(
- HANDLE OldFileHandle, HANDLE NewFileHandle)
-{
- ULONG i;
- BOOLEAN dup;
-
- //
- // called from NtDuplicateObject to duplicate the "recoverability"
- // of the old handle to the new handle. needed in particular for
- // SHFileOperation to recover correctly on Windows Vista
- //
-
- dup = FALSE;
-
- EnterCriticalSection(&File_HandleOnClose_CritSec);
-
- FILE_ON_CLOSE* on_close = map_get(&File_HandleOnClose, OldFileHandle);
- if (on_close) {
- for (i = 0; i < MAX_CLOSE_HANDLERS; i++) {
- if(on_close->CloseHandlers[i] == File_NotifyRecover)
- dup = TRUE;
- }
- }
-
- LeaveCriticalSection(&File_HandleOnClose_CritSec);
-
- if (dup && NewFileHandle)
- File_RegisterCloseHandler(NewFileHandle, File_NotifyRecover);
-}
-
-
-//---------------------------------------------------------------------------
-// File_NotifyRecover
-//---------------------------------------------------------------------------
-
-
-_FX void File_NotifyRecover(HANDLE FileHandle)
-{
- THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
-
- NTSTATUS status;
- union {
- FILE_NETWORK_OPEN_INFORMATION open;
- ULONG space[16];
- } info;
- ULONG length;
- ULONG FileFlags;
- UNICODE_STRING uni;
- WCHAR *TruePath, *CopyPath;
- IO_STATUS_BLOCK IoStatusBlock;
-
- //
- // send request to SbieCtrl (if recoverable file)
- //
-
- Dll_PushTlsNameBuffer(TlsData);
-
- do {
-
- RtlInitUnicodeString(&uni, L"");
- status = File_GetName(
- FileHandle, &uni, &TruePath, &CopyPath, &FileFlags);
- if (! NT_SUCCESS(status))
- break;
-
- if (! (FileFlags & FGN_IS_BOXED_PATH))
- break;
-
- //
- // Immediate Recovery
- //
-
- if (!File_IsRecoverable(TruePath))
- break;
-
- status = __sys_NtQueryInformationFile(
- FileHandle, &IoStatusBlock, &info,
- sizeof(FILE_NETWORK_OPEN_INFORMATION),
- FileNetworkOpenInformation);
-
- if (! NT_SUCCESS(status))
- break;
- if (info.open.EndOfFile.QuadPart == 0)
- break;
-
- //
- // queue immediate recovery elements for later processing
- //
-
- FILE_RECOVER_FOLDER *rec;
- ULONG TruePath_len;
-
- EnterCriticalSection(&File_RecHandles_CritSec);
-
- TruePath_len = wcslen(TruePath);
-
- rec = List_Head(&File_RecPaths);
- while (rec) {
- if (rec->path_len == TruePath_len)
- if (_wcsicmp(rec->path, TruePath) == 0)
- break;
- rec = List_Next(rec);
- }
-
- if (! rec) {
-
- length = sizeof(FILE_RECOVER_FOLDER)
- + (TruePath_len + 1) * sizeof(WCHAR);
- rec = Dll_Alloc(length);
-
- rec->ticks = GetTickCount();
-
- wcscpy(rec->path, TruePath);
- rec->path_len = TruePath_len;
-
- List_Insert_After(&File_RecPaths, NULL, rec);
- }
-
- LeaveCriticalSection(&File_RecHandles_CritSec);
- if (rec)
- File_DoAutoRecover(TRUE);
-
- } while (0);
-
- Dll_PopTlsNameBuffer(TlsData);
-}
-
-
//---------------------------------------------------------------------------
// File_RtlGetCurrentDirectory_U
//---------------------------------------------------------------------------
@@ -3633,9 +3188,11 @@ _FX NTSTATUS File_SetReparsePoint(
__leave;
}
- //if (File_Snapshot != NULL)
- // File_FindSnapshotPath(&CopyPath);
-
+ //if (File_Snapshot != NULL){
+ // WCHAR* TmplName = File_FindSnapshotPath(CopyPath);
+ // if (TmplName) CopyPath = TmplName;
+ //}
+
//SourcePath = Dll_Alloc((wcslen(CopyPath) + 4) * sizeof(WCHAR));
//wcscpy(SourcePath, CopyPath);
@@ -3764,265 +3321,6 @@ _FX NTSTATUS File_SetReparsePoint(
}
-//---------------------------------------------------------------------------
-// File_DoAutoRecover
-//---------------------------------------------------------------------------
-
-
-_FX void File_DoAutoRecover(BOOLEAN force)
-{
- static ULONG last_ticks = 0;
-
- ULONG LastError;
- THREAD_DATA *TlsData = Dll_GetTlsData(&LastError);
-
- ULONG ticks = GetTickCount();
- if (force || (ticks - last_ticks > 400)) {
-
- last_ticks = ticks;
-
- if (TryEnterCriticalSection(&File_RecHandles_CritSec)) {
-
- if (List_Head(&File_RecPaths)) {
-
- Dll_PushTlsNameBuffer(TlsData);
-
- File_DoAutoRecover_2(force, ticks);
-
- Dll_PopTlsNameBuffer(TlsData);
- }
-
- LeaveCriticalSection(&File_RecHandles_CritSec);
- }
- }
-
- SetLastError(LastError);
-}
-
-
-//---------------------------------------------------------------------------
-// File_DoAutoRecover_2
-//---------------------------------------------------------------------------
-
-
-_FX void File_DoAutoRecover_2(BOOLEAN force, ULONG ticks)
-{
- NTSTATUS status;
- SYSTEM_HANDLE_INFORMATION *info = NULL;
- FILE_GET_ALL_HANDLES_RPL *rpl = NULL;
- ULONG info_len = 64, len, i;
- WCHAR *pathbuf;
- ULONG UseCount = 0;
- FILE_RECOVER_FOLDER *rec;
- UCHAR FileObjectTypeNumber = 0;
-
- //
- // get list of open handles in the system
- //
-
- for (i = 0; i < 5; ++i) {
-
- info = Dll_AllocTemp(info_len);
-
- status = NtQuerySystemInformation(
- SystemHandleInformation, info, info_len, &len);
-
- if (NT_SUCCESS(status))
- break;
-
- Dll_Free(info);
- info_len = len + 64;
-
- if (status == STATUS_BUFFER_OVERFLOW ||
- status == STATUS_INFO_LENGTH_MISMATCH ||
- status == STATUS_BUFFER_TOO_SMALL) {
-
- continue;
- }
-
- break;
- }
-
- if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0) // don't try that in app mode, we had a proepr token
- if (status == STATUS_ACCESS_DENIED) {
-
- //
- // on Windows 8.1, NtQuerySystemInformation fails, probably because
- // we are running without any privileges, so go through SbieSvc
- //
-
- MSG_HEADER req;
- req.length = sizeof(req);
- req.msgid = MSGID_FILE_GET_ALL_HANDLES;
- rpl = (FILE_GET_ALL_HANDLES_RPL *)SbieDll_CallServer(&req);
-
- if (rpl) {
- info = NULL;
- status = STATUS_SUCCESS;
- }
- }
-
- if (! NT_SUCCESS(status))
- return;
-
- pathbuf = Dll_AllocTemp(1024);
-
- //
- // scan list of queued recovery files
- //
-
- rec = List_Head(&File_RecPaths);
- while (rec) {
-
- FILE_RECOVER_FOLDER *rec_next = List_Next(rec);
- BOOLEAN send2199 = FALSE;
-
- if (force)
- send2199 = TRUE;
- else {
- if (ticks - rec->ticks >= 1000) {
- ULONG UseCount = File_DoAutoRecover_3(
- rec->path, pathbuf, info, rpl, &FileObjectTypeNumber);
- if (UseCount == 0)
- send2199 = TRUE;
- }
- }
-
- if (send2199) {
- WCHAR *colon = wcschr(rec->path, L':');
- if (!colon) {
-
- UNICODE_STRING uni;
- WCHAR *TruePath, *CopyPath;
- RtlInitUnicodeString(&uni, rec->path);
- status = File_GetName(NULL, &uni, &TruePath, &CopyPath, NULL);
-
- const WCHAR* strings[] = { Dll_BoxName, rec->path, CopyPath, NULL };
- SbieApi_LogMsgExt(2199, strings);
- }
- List_Remove(&File_RecPaths, rec);
- }
-
- rec = rec_next;
- }
-
- //
- // finish
- //
-
- Dll_Free(pathbuf);
- if (info)
- Dll_Free(info);
- if (rpl)
- Dll_Free(rpl);
-}
-
-
-//---------------------------------------------------------------------------
-// File_DoAutoRecover_3
-//---------------------------------------------------------------------------
-
-
-_FX ULONG File_DoAutoRecover_3(
- const WCHAR *PathToFind, WCHAR *PathBuf1024,
- SYSTEM_HANDLE_INFORMATION *info, FILE_GET_ALL_HANDLES_RPL *rpl,
- UCHAR *FileObjectTypeNumber)
-{
- HANDLE FileHandle;
- ULONG UseCount, i;
-
- //
- // scan handles for current process
- //
-
- UseCount = 0;
-
- if (info) {
-
- for (i = 0; i < info->Count; ++i) {
-
- HANDLE_INFO *hi = &info->HandleInfo[i];
-
- if (hi->ProcessId != Dll_ProcessId)
- continue;
-
- FileHandle = (HANDLE)(ULONG_PTR)hi->Handle;
-
- UseCount += File_DoAutoRecover_4(
- PathToFind, PathBuf1024,
- FileHandle, hi->ObjectTypeNumber, FileObjectTypeNumber);
- }
-
- } else if (rpl) {
-
- for (i = 0; i < rpl->num_handles; ++i) {
-
- UCHAR objtype = (UCHAR)(rpl->handles[i] >> 24);
-
- FileHandle = (HANDLE)(ULONG_PTR)(rpl->handles[i] & 0x00FFFFFFU);
-
- UseCount += File_DoAutoRecover_4(
- PathToFind, PathBuf1024,
- FileHandle, objtype, FileObjectTypeNumber);
- }
- }
-
- return UseCount;
-}
-
-
-//---------------------------------------------------------------------------
-// File_DoAutoRecover_4
-//---------------------------------------------------------------------------
-
-
-_FX ULONG File_DoAutoRecover_4(
- const WCHAR *PathToFind, WCHAR *PathBuf1024,
- HANDLE FileHandle, UCHAR ObjectTypeNumber, UCHAR *FileObjectTypeNumber)
-{
- UNICODE_STRING uni;
- WCHAR *TruePath, *CopyPath;
- NTSTATUS status;
-
- //
- // make sure the handle is to a file
- //
-
- if (*FileObjectTypeNumber) {
-
- if (ObjectTypeNumber != *FileObjectTypeNumber)
- return 0;
-
- } else {
-
- if (Obj_GetObjectType(FileHandle) == OBJ_TYPE_FILE) {
-
- *FileObjectTypeNumber = ObjectTypeNumber;
-
- } else
- return 0;
- }
-
- //
- // get file name
- //
-
- status = File_GetFileName(FileHandle, 1000, PathBuf1024);
- if (! NT_SUCCESS(status))
- return 0;
-
- RtlInitUnicodeString(&uni, PathBuf1024);
- status = File_GetName(NULL, &uni, &TruePath, &CopyPath, NULL);
- if (! NT_SUCCESS(status))
- return 0;
-
- if (_wcsicmp(PathToFind, TruePath) == 0)
- return 1;
-
- return 0;
-}
-
-
//---------------------------------------------------------------------------
// File_MyQueryDirectoryFile
//---------------------------------------------------------------------------
@@ -4049,134 +3347,6 @@ _FX NTSTATUS File_MyQueryDirectoryFile(
}
-//---------------------------------------------------------------------------
-// File_MsoDll
-//---------------------------------------------------------------------------
-
-
-_FX BOOLEAN File_MsoDll(HMODULE module)
-{
- //
- // hack for File_IsRecoverable
- //
-
- File_MsoDllLoaded = TRUE;
- return TRUE;
-}
-
-
-//---------------------------------------------------------------------------
-// File_Scramble_Char
-//---------------------------------------------------------------------------
-
-
-_FX WCHAR File_Scramble_Char(WCHAR wValue, int Key, BOOLEAN scram)
-{
- //
- // This function allows to scramble file name charakters properly,
- // i.e. no invalid cahacters can result fron this operation.
- // It does not scramble invalid charakters like: " * / : < > ? \ |
- // And it does not scramble ~
- // The entropy of the scrambler is 25,5bit (i.e. 52 million values)
- //
-
- char reserved_ch[] = { '\"', '*', '/', ':', '<', '>', '?', '\\', '|' };
- const int reserved_count = 9;
- const int max_ch = 0x7E - reserved_count - 0x20;
-
- int uValue = (wValue & 0x7F);
- if (uValue < 0x20 || uValue >= 0x7E) // < space || >= ~
- return wValue;
- for (int i = 0; i < reserved_count; i++)
- if (uValue == reserved_ch[i]) return wValue;
-
- Key &= 0x7f;
- while (Key >= max_ch)
- Key -= max_ch;
- if (!scram)
- Key = -Key;
-
- for (int i = 1; i <= reserved_count; i++)
- if (uValue > reserved_ch[reserved_count - i]) uValue -= 1;
- uValue -= 0x20;
-
- uValue += Key;
-
- if (uValue >= max_ch)
- uValue -= max_ch;
- else if (uValue < 0)
- uValue += max_ch;
-
- uValue += 0x20;
- for (int i = 0; i < reserved_count; i++)
- if (uValue >= reserved_ch[i]) uValue += 1;
-
- return uValue;
-}
-
-
-//---------------------------------------------------------------------------
-// File_ScrambleShortName
-//---------------------------------------------------------------------------
-
-
-_FX void File_ScrambleShortName(WCHAR* ShortName, CCHAR* ShortNameBytes, ULONG ScramKey)
-{
- CCHAR ShortNameLength = *ShortNameBytes / sizeof(WCHAR);
-
- CCHAR dot_pos;
- WCHAR *dot = wcsrchr(ShortName, L'.');
- if (dot == NULL) {
- dot_pos = ShortNameLength;
- if (ShortNameLength >= 12)
- return; // this should never not happen!
- ShortName[ShortNameLength++] = L'.';
- }
- else
- dot_pos = (CCHAR)(dot - ShortName);
-
- while (ShortNameLength - dot_pos < 4)
- {
- if (ShortNameLength >= 12)
- return; // this should never not happen!
- ShortName[ShortNameLength++] = L' ';
- }
-
- *ShortNameBytes = ShortNameLength * sizeof(WCHAR);
-
- if (dot_pos > 0)
- ShortName[dot_pos - 1] = File_Scramble_Char(ShortName[dot_pos - 1], ((char*)&ScramKey)[0], TRUE);
- for (int i = 1; i <= 3; i++)
- ShortName[dot_pos + i] = File_Scramble_Char(ShortName[dot_pos + i], ((char*)&ScramKey)[i], TRUE);
-}
-
-
-//---------------------------------------------------------------------------
-// File_UnScrambleShortName
-//---------------------------------------------------------------------------
-
-
-_FX void File_UnScrambleShortName(WCHAR* ShortName, ULONG ScramKey)
-{
- CCHAR ShortNameLength = (CCHAR)wcslen(ShortName);
-
- WCHAR *dot = wcsrchr(ShortName, L'.');
- if (dot == NULL)
- return; // not a scrambled short name.
- CCHAR dot_pos = (CCHAR)(dot - ShortName);
-
- if (dot_pos > 0)
- ShortName[dot_pos - 1] = File_Scramble_Char(ShortName[dot_pos - 1], ((char*)&ScramKey)[0], FALSE);
- for (int i = 1; i <= 3; i++)
- ShortName[dot_pos + i] = File_Scramble_Char(ShortName[dot_pos + i], ((char*)&ScramKey)[i], FALSE);
-
- while (ShortName[ShortNameLength - 1] == L' ')
- ShortName[ShortNameLength-- - 1] = 0;
- if (ShortName[ShortNameLength - 1] == L'.')
- ShortName[ShortNameLength-- - 1] = 0;
-}
-
-
//---------------------------------------------------------------------------
// Key_CreateBaseFolders
//---------------------------------------------------------------------------
diff --git a/Sandboxie/core/dll/file_init.c b/Sandboxie/core/dll/file_init.c
index 71462449..584ab5ce 100644
--- a/Sandboxie/core/dll/file_init.c
+++ b/Sandboxie/core/dll/file_init.c
@@ -106,8 +106,6 @@ static WCHAR *File_AllocAndInitEnvironment_2(
static void File_AdjustDrives(
ULONG path_drive_index, BOOLEAN subst, const WCHAR *path);
-static void File_InitSnapshots(void);
-
//---------------------------------------------------------------------------
// Variables
@@ -122,20 +120,6 @@ static const WCHAR *File_DeviceMap_EnvVar = ENV_VAR_PFX L"DEVICE_MAP";
#undef ENV_VAR_PFX
-//---------------------------------------------------------------------------
-// File_InitHandles
-//---------------------------------------------------------------------------
-
-
-_FX BOOLEAN File_InitHandles(void)
-{
- InitializeCriticalSection(&File_HandleOnClose_CritSec);
- map_init(&File_HandleOnClose, Dll_Pool);
-
- return TRUE;
-}
-
-
//---------------------------------------------------------------------------
// File_Init
//---------------------------------------------------------------------------
@@ -158,6 +142,10 @@ _FX BOOLEAN File_Init(void)
File_DriveAddSN = SbieApi_QueryConfBool(NULL, L"UseVolumeSerialNumbers", FALSE);
+ File_Delete_v2 = SbieApi_QueryConfBool(NULL, L"UseFileDeleteV2", FALSE);
+
+ File_NoReparse = SbieApi_QueryConfBool(NULL, L"NoPathReparse", FALSE);
+
if (! File_InitDrives(0xFFFFFFFF))
return FALSE;
@@ -166,6 +154,16 @@ _FX BOOLEAN File_Init(void)
return FALSE;
}
+ if (Dll_OsBuild >= 6000) { // needed for File_GetFileName used indirectly by File_InitRecoverFolders
+
+ void *GetFinalPathNameByHandleW =
+ GetProcAddress(Dll_KernelBase ? Dll_KernelBase : Dll_Kernel32,
+ "GetFinalPathNameByHandleW");
+ if (GetFinalPathNameByHandleW) {
+ SBIEDLL_HOOK(File_,GetFinalPathNameByHandleW);
+ }
+ }
+
File_InitSnapshots();
File_InitRecoverFolders();
@@ -230,16 +228,6 @@ _FX BOOLEAN File_Init(void)
}
}
- if (Dll_OsBuild >= 6000) {
-
- void *GetFinalPathNameByHandleW =
- GetProcAddress(Dll_KernelBase ? Dll_KernelBase : Dll_Kernel32,
- "GetFinalPathNameByHandleW");
- if (GetFinalPathNameByHandleW) {
- SBIEDLL_HOOK(File_,GetFinalPathNameByHandleW);
- }
- }
-
if (Dll_OsBuild >= 8400 && Dll_IsSystemSid) {
// see File_GetTempPathW in file file_misc.c
GetTempPathW = GetProcAddress(Dll_KernelBase, "GetTempPathW");
@@ -248,6 +236,16 @@ _FX BOOLEAN File_Init(void)
}
}
+
+ if (File_Delete_v2)
+ File_InitDelete_v2();
+
+ // Note: loading the file tha way its done now only works once file hooks are installed so this must eb here
+ extern BOOLEAN Key_Delete_v2;
+ extern BOOLEAN Key_InitDelete_v2();
+ if (Key_Delete_v2)
+ Key_InitDelete_v2();
+
//
// support for Google Chrome flash plugin process
//
@@ -517,6 +515,7 @@ _FX BOOLEAN File_InitDrives(ULONG DriveMask)
status = NtOpenSymbolicLinkObject(
&handle, SYMBOLIC_LINK_QUERY, &objattrs);
+ if (!Dll_CompartmentMode) // NoDriverAssist
if (status == STATUS_ACCESS_DENIED) {
//
@@ -1747,6 +1746,7 @@ _FX void File_GetSetDeviceMap(WCHAR *DeviceMap96)
status = NtOpenDirectoryObject(&handle, DIRECTORY_QUERY, &objattrs);
+ if (!Dll_CompartmentMode) // NoDriverAssist
if (status == STATUS_ACCESS_DENIED) {
//
@@ -1787,58 +1787,4 @@ _FX void File_GetSetDeviceMap(WCHAR *DeviceMap96)
}
}
}
-}
-
-
-//---------------------------------------------------------------------------
-// File_InitSnapshots
-//---------------------------------------------------------------------------
-
-// CRC
-#define CRC_WITH_ADLERTZUK64
-#include "common/crc.c"
-
-_FX void File_InitSnapshots(void)
-{
- WCHAR ShapshotsIni[MAX_PATH] = { 0 };
- wcscpy(ShapshotsIni, Dll_BoxFilePath);
- wcscat(ShapshotsIni, L"\\Snapshots.ini");
- SbieDll_TranslateNtToDosPath(ShapshotsIni);
-
- WCHAR Shapshot[16] = { 0 };
- GetPrivateProfileStringW(L"Current", L"Snapshot", L"", Shapshot, 16, ShapshotsIni);
-
- if (*Shapshot == 0)
- return; // not using snapshots
-
- File_Snapshot = Dll_Alloc(sizeof(FILE_SNAPSHOT));
- memzero(File_Snapshot, sizeof(FILE_SNAPSHOT));
- wcscpy(File_Snapshot->ID, Shapshot);
- File_Snapshot->IDlen = wcslen(Shapshot);
- FILE_SNAPSHOT* Cur_Snapshot = File_Snapshot;
- File_Snapshot_Count = 1;
-
- for (;;)
- {
- Cur_Snapshot->ScramKey = CRC32(Cur_Snapshot->ID, Cur_Snapshot->IDlen * sizeof(WCHAR));
-
- WCHAR ShapshotId[26] = L"Snapshot_";
- wcscat(ShapshotId, Shapshot);
-
- //WCHAR ShapshotName[34] = { 0 };
- //GetPrivateProfileStringW(ShapshotId, L"Name", L"", ShapshotName, 34, ShapshotsIni);
- //wcscpy(Cur_Snapshot->Name, ShapshotName);
-
- GetPrivateProfileStringW(ShapshotId, L"Parent", L"", Shapshot, 16, ShapshotsIni);
-
- if (*Shapshot == 0)
- break; // no more snapshots
-
- Cur_Snapshot->Parent = Dll_Alloc(sizeof(FILE_SNAPSHOT));
- memzero(Cur_Snapshot->Parent, sizeof(FILE_SNAPSHOT));
- wcscpy(Cur_Snapshot->Parent->ID, Shapshot);
- Cur_Snapshot->Parent->IDlen = wcslen(Shapshot);
- Cur_Snapshot = Cur_Snapshot->Parent;
- File_Snapshot_Count++;
- }
-}
+}
\ No newline at end of file
diff --git a/Sandboxie/core/dll/file_link.c b/Sandboxie/core/dll/file_link.c
index 406f6c06..3e2b33ad 100644
--- a/Sandboxie/core/dll/file_link.c
+++ b/Sandboxie/core/dll/file_link.c
@@ -1,5 +1,6 @@
/*
* Copyright 2004-2020 Sandboxie Holdings, LLC
+ * Copyright 2020-2022 David Xanatos, xanasoft.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -470,6 +471,9 @@ _FX WCHAR *File_TranslateTempLinks(
WCHAR *ret;
ULONG TruePath_len, ret_len;
+ if (File_NoReparse)
+ return NULL;
+
//
// entry
//
@@ -794,12 +798,13 @@ _FX WCHAR *File_TranslateTempLinks_2(WCHAR *input_str, ULONG input_len)
_FX NTSTATUS File_GetFileName(HANDLE FileHandle, ULONG NameLen, WCHAR* NameBuf)
{
- //extern P_GetFinalPathNameByHandle __sys_GetFinalPathNameByHandleW;
- //if (__sys_GetFinalPathNameByHandleW(FileHandle, NameBuf, NameLen, VOLUME_NAME_NT) > 0)
- // return STATUS_SUCCESS;
- //return STATUS_UNSUCCESSFUL;
+ if (!Dll_CompartmentMode || !__sys_GetFinalPathNameByHandleW) // NoDriverAssist
+ return SbieApi_GetFileName(FileHandle, NameLen, NameBuf);
- return SbieApi_GetFileName(FileHandle, NameLen, NameBuf);
+ // available in vista and later
+ if (__sys_GetFinalPathNameByHandleW(FileHandle, NameBuf, NameLen, VOLUME_NAME_NT) > 0)
+ return STATUS_SUCCESS;
+ return STATUS_UNSUCCESSFUL;
}
diff --git a/Sandboxie/core/dll/file_misc.c b/Sandboxie/core/dll/file_misc.c
index c83f61e6..a960432d 100644
--- a/Sandboxie/core/dll/file_misc.c
+++ b/Sandboxie/core/dll/file_misc.c
@@ -1,6 +1,6 @@
/*
* Copyright 2004-2020 Sandboxie Holdings, LLC
- * Copyright 2020 David Xanatos, xanasoft.com
+ * Copyright 2020-2022 David Xanatos, xanasoft.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -329,8 +329,10 @@ _FX void File_ReplaceFileW_3(
(*FileFlags) &= FGN_IS_BOXED_PATH;
if (*FileFlags) {
- if (File_Snapshot != NULL)
- File_FindSnapshotPath(&CopyPath);
+ if (File_Snapshot != NULL) {
+ WCHAR* TmplName = File_FindSnapshotPath(CopyPath);
+ if (TmplName) CopyPath = TmplName;
+ }
len = (wcslen(CopyPath) + 1) * sizeof(WCHAR);
path = Dll_AllocTemp(len);
diff --git a/Sandboxie/core/dll/file_pipe.c b/Sandboxie/core/dll/file_pipe.c
index 3e8edad2..6d1268bc 100644
--- a/Sandboxie/core/dll/file_pipe.c
+++ b/Sandboxie/core/dll/file_pipe.c
@@ -1164,7 +1164,7 @@ _FX NTSTATUS File_NtFsControlFile(
InputBuffer, InputBufferLength);
SetLastError(LastError);
- } else if (IoControlCode == FSCTL_PIPE_IMPERSONATE) {
+ } else if (IoControlCode == FSCTL_PIPE_IMPERSONATE && !Dll_CompartmentMode) {
SbieApi_Log(2205, L"ImpersonateNamedPipe");
if (Proc_ImpersonateSelf(TRUE))
diff --git a/Sandboxie/core/dll/file_recovery.c b/Sandboxie/core/dll/file_recovery.c
new file mode 100644
index 00000000..be97b1ea
--- /dev/null
+++ b/Sandboxie/core/dll/file_recovery.c
@@ -0,0 +1,726 @@
+/*
+ * Copyright 2004-2020 Sandboxie Holdings, LLC
+ * Copyright 2020-2022 David Xanatos, xanasoft.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+//---------------------------------------------------------------------------
+//
+// Immediate Recovery for Files
+//
+//---------------------------------------------------------------------------
+
+
+//---------------------------------------------------------------------------
+// Functions
+//---------------------------------------------------------------------------
+
+
+static void File_InitRecoverFolders(void);
+
+static void File_InitRecoverList(
+ const WCHAR *setting, LIST *list, BOOLEAN MustBeValidPath,
+ WCHAR *buf, ULONG buf_len);
+
+static BOOLEAN File_IsRecoverable(const WCHAR *TruePath);
+
+static void File_DoAutoRecover_2(BOOLEAN force, ULONG ticks);
+
+static ULONG File_DoAutoRecover_3(
+ const WCHAR *PathToFind, WCHAR *PathBuf1024,
+ SYSTEM_HANDLE_INFORMATION *info, FILE_GET_ALL_HANDLES_RPL *rpl,
+ UCHAR *FileObjectTypeNumber);
+
+static ULONG File_DoAutoRecover_4(
+ const WCHAR *PathToFind, WCHAR *PathBuf1024,
+ HANDLE FileHandle, UCHAR ObjectTypeNumber, UCHAR *FileObjectTypeNumber);
+
+
+//---------------------------------------------------------------------------
+// Variables
+//---------------------------------------------------------------------------
+
+
+static LIST File_RecoverFolders;
+static LIST File_RecoverIgnores;
+
+static LIST File_RecPaths;
+static CRITICAL_SECTION File_RecHandles_CritSec;
+
+static BOOLEAN File_MsoDllLoaded = FALSE;
+
+//---------------------------------------------------------------------------
+// Structures and Types
+//---------------------------------------------------------------------------
+
+
+typedef struct _FILE_RECOVER_FOLDER {
+
+ LIST_ELEM list_elem;
+ ULONG ticks; // for File_RecPaths
+ ULONG path_len;
+ WCHAR path[1];
+
+} FILE_RECOVER_FOLDER;
+
+
+//---------------------------------------------------------------------------
+// File_InitRecoverFolders
+//---------------------------------------------------------------------------
+
+
+_FX void File_InitRecoverFolders(void)
+{
+ //
+ // init list of recoverable file handles
+ //
+
+ List_Init(&File_RecoverFolders);
+ List_Init(&File_RecoverIgnores);
+
+ InitializeCriticalSectionAndSpinCount(&File_RecHandles_CritSec, 1000);
+
+ List_Init(&File_RecPaths);
+
+ //
+ // init list of recover folders
+ //
+
+ if (SbieApi_QueryConfBool(NULL, L"AutoRecover", FALSE)) {
+
+ ULONG buf_len = 4096 * sizeof(WCHAR);
+ WCHAR *buf = Dll_AllocTemp(buf_len);
+
+ File_InitRecoverList(
+ L"RecoverFolder", &File_RecoverFolders, TRUE, buf, buf_len);
+
+ File_InitRecoverList(
+ L"AutoRecoverIgnore", &File_RecoverIgnores, FALSE, buf, buf_len);
+
+ Dll_Free(buf);
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// File_InitRecoverList
+//---------------------------------------------------------------------------
+
+
+_FX void File_InitRecoverList(
+ const WCHAR *setting, LIST *list, BOOLEAN MustBeValidPath,
+ WCHAR *buf, ULONG buf_len)
+{
+ UNICODE_STRING uni;
+ WCHAR *TruePath, *CopyPath, *ReparsedPath;
+ FILE_RECOVER_FOLDER *fold;
+
+ ULONG index = 0;
+ while (1) {
+
+ NTSTATUS status = SbieApi_QueryConf(
+ NULL, setting, index, buf, buf_len - 16 * sizeof(WCHAR));
+ if (! NT_SUCCESS(status))
+ break;
+ ++index;
+
+ RtlInitUnicodeString(&uni, buf);
+ status = File_GetName(NULL, &uni, &TruePath, &CopyPath, NULL);
+
+ ReparsedPath = NULL;
+
+ if (NT_SUCCESS(status) && MustBeValidPath) {
+
+ ReparsedPath = File_TranslateTempLinks(TruePath, FALSE);
+ if (ReparsedPath)
+ TruePath = ReparsedPath;
+
+ } else if ((! NT_SUCCESS(status)) && (! MustBeValidPath)) {
+
+ TruePath = buf;
+ status = STATUS_SUCCESS;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ ULONG len = wcslen(TruePath);
+ if (len && TruePath[len - 1] == L'\\') {
+ TruePath[len - 1] = L'\0';
+ --len;
+ }
+ len = sizeof(FILE_RECOVER_FOLDER)
+ + (len + 1) * sizeof(WCHAR);
+ fold = Dll_Alloc(len);
+
+ fold->ticks = 0; // not used
+
+ wcscpy(fold->path, TruePath);
+ fold->path_len = wcslen(fold->path);
+
+ List_Insert_After(list, NULL, fold);
+ }
+
+ if (ReparsedPath)
+ Dll_Free(ReparsedPath);
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// File_IsRecoverable
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN File_IsRecoverable(
+ const WCHAR *TruePath)
+{
+ const WCHAR *save_TruePath;
+ FILE_RECOVER_FOLDER *fold;
+ const WCHAR *ptr;
+ ULONG TruePath_len;
+ ULONG PrefixLen;
+ BOOLEAN ok;
+
+ //
+ // if we have a path that looks like
+ // \Device\LanmanRedirector\;Q:000000000000b09f\server\share\f1.txt
+ // \Device\Mup\;LanmanRedirector\;Q:000000000000b09f\server\share\f1.txt
+ // then translate to
+ // \Device\Mup\server\share\f1.txt
+ // and test again. We do this because the SbieDrv records paths
+ // in the \Device\Mup format. See SbieDrv::File_TranslateShares.
+ //
+
+ save_TruePath = TruePath;
+
+ if (_wcsnicmp(TruePath, File_Redirector, File_RedirectorLen) == 0)
+ PrefixLen = File_RedirectorLen;
+ else if (_wcsnicmp(TruePath, File_DfsClientRedir, File_DfsClientRedirLen) == 0)
+ PrefixLen = File_DfsClientRedirLen;
+ else if (_wcsnicmp(TruePath, File_HgfsRedir, File_HgfsRedirLen) == 0)
+ PrefixLen = File_HgfsRedirLen;
+ else if (_wcsnicmp(TruePath, File_MupRedir, File_MupRedirLen) == 0)
+ PrefixLen = File_MupRedirLen;
+ else
+ PrefixLen = 0;
+
+ if (PrefixLen && TruePath[PrefixLen] == L';') {
+
+ WCHAR *ptr = wcschr(TruePath + PrefixLen, L'\\');
+ if (ptr && ptr[0] && ptr[1]) {
+
+ ULONG len1 = wcslen(ptr + 1);
+ ULONG len2 = (File_MupLen + len1 + 8) * sizeof(WCHAR);
+ WCHAR *path2 = Dll_Alloc(len2);
+ wmemcpy(path2, File_Mup, File_MupLen);
+ wmemcpy(path2 + File_MupLen, ptr + 1, len1 + 1);
+
+ TruePath = (const WCHAR *)path2;
+ }
+ }
+
+ //
+ // look for the TruePath in the list of RecoverFolder settings
+ //
+
+ ok = FALSE;
+
+ fold = List_Head(&File_RecoverFolders);
+ while (fold) {
+
+ if (_wcsnicmp(fold->path, TruePath, fold->path_len) == 0) {
+ ptr = TruePath + fold->path_len;
+ if (*ptr == L'\\' || *ptr == L'\0') {
+ ok = TRUE;
+ break;
+ }
+ }
+
+ fold = List_Next(fold);
+ }
+
+ if (! ok)
+ goto finish;
+
+ //
+ // ignore files that begin with ~$ (Microsoft Office temp files)
+ // or that don't have a file type extension (probably temp files)
+ //
+
+ if (File_MsoDllLoaded) {
+
+ ptr = wcsrchr(TruePath, L'\\');
+ if (ptr) {
+ if (ptr[1] == L'~' && ptr[2] == L'$')
+ ok = FALSE;
+ else {
+ ptr = wcschr(ptr, L'.');
+ if (! ptr)
+ ok = FALSE;
+ }
+ if (! ok)
+ goto finish;
+ }
+ }
+
+ //
+ // look for TruePath in the list of AutoRecoverIgnore settings
+ //
+
+ TruePath_len = wcslen(TruePath);
+
+ fold = List_Head(&File_RecoverIgnores);
+ while (fold) {
+
+ if (_wcsnicmp(fold->path, TruePath, fold->path_len) == 0) {
+ ptr = TruePath + fold->path_len;
+ if (*ptr == L'\\' || *ptr == L'\0') {
+ ok = FALSE;
+ break;
+ }
+ }
+
+ if (TruePath_len >= fold->path_len) {
+ ptr = TruePath + TruePath_len - fold->path_len;
+ if (_wcsicmp(fold->path, ptr) == 0) {
+ ok = FALSE;
+ break;
+ }
+ }
+
+ fold = List_Next(fold);
+ }
+
+ //
+ // finish
+ //
+
+finish:
+
+ if (TruePath != save_TruePath)
+ Dll_Free((WCHAR *)TruePath);
+ return ok;
+}
+
+
+//---------------------------------------------------------------------------
+// File_RecordRecover
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN File_RecordRecover(HANDLE FileHandle, const WCHAR *TruePath)
+{
+ BOOLEAN IsRecoverable;
+
+ IsRecoverable = File_IsRecoverable(TruePath);
+
+ //
+ // in a Chrome sandbox process, handles are opened by the broker,
+ // so skip checking against the list of recorded file handles
+ //
+
+ // Note: this does not seam to be required anymore
+
+ //if ((! IsRecoverable) && Dll_ChromeSandbox) {
+ //
+ // FILE_ACCESS_INFORMATION info;
+ //
+ // status = __sys_NtQueryInformationFile(
+ // FileHandle, &IoStatusBlock, &info,
+ // sizeof(FILE_ACCESS_INFORMATION), FileAccessInformation);
+ //
+ // if (NT_SUCCESS(status) && (info.AccessFlags & FILE_WRITE_DATA))
+ // IsRecoverable = 2; //TRUE; // we still want to return false when called from File_NtCreateFileImpl
+ // else
+ // IsRecoverable = FALSE;
+ //}
+
+ if (IsRecoverable != FALSE)
+ Handle_RegisterCloseHandler(FileHandle, File_NotifyRecover);
+
+ return IsRecoverable == TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+// File_NotifyRecover
+//---------------------------------------------------------------------------
+
+
+_FX void File_NotifyRecover(HANDLE FileHandle)
+{
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ NTSTATUS status;
+ union {
+ FILE_NETWORK_OPEN_INFORMATION open;
+ ULONG space[16];
+ } info;
+ ULONG length;
+ ULONG FileFlags;
+ UNICODE_STRING uni;
+ WCHAR *TruePath, *CopyPath;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ //
+ // send request to SbieCtrl (if recoverable file)
+ //
+
+ Dll_PushTlsNameBuffer(TlsData);
+
+ do {
+
+ RtlInitUnicodeString(&uni, L"");
+ status = File_GetName(
+ FileHandle, &uni, &TruePath, &CopyPath, &FileFlags);
+ if (! NT_SUCCESS(status))
+ break;
+
+ if (! (FileFlags & FGN_IS_BOXED_PATH))
+ break;
+
+ //
+ // Immediate Recovery
+ //
+
+ if (!File_IsRecoverable(TruePath))
+ break;
+
+ status = __sys_NtQueryInformationFile(
+ FileHandle, &IoStatusBlock, &info,
+ sizeof(FILE_NETWORK_OPEN_INFORMATION),
+ FileNetworkOpenInformation);
+
+ if (! NT_SUCCESS(status))
+ break;
+ if (info.open.EndOfFile.QuadPart == 0)
+ break;
+
+ //
+ // queue immediate recovery elements for later processing
+ //
+
+ FILE_RECOVER_FOLDER *rec;
+ ULONG TruePath_len;
+
+ EnterCriticalSection(&File_RecHandles_CritSec);
+
+ TruePath_len = wcslen(TruePath);
+
+ rec = List_Head(&File_RecPaths);
+ while (rec) {
+ if (rec->path_len == TruePath_len)
+ if (_wcsicmp(rec->path, TruePath) == 0)
+ break;
+ rec = List_Next(rec);
+ }
+
+ if (! rec) {
+
+ length = sizeof(FILE_RECOVER_FOLDER)
+ + (TruePath_len + 1) * sizeof(WCHAR);
+ rec = Dll_Alloc(length);
+
+ rec->ticks = GetTickCount();
+
+ wcscpy(rec->path, TruePath);
+ rec->path_len = TruePath_len;
+
+ List_Insert_After(&File_RecPaths, NULL, rec);
+ }
+
+ LeaveCriticalSection(&File_RecHandles_CritSec);
+ if (rec)
+ File_DoAutoRecover(TRUE);
+
+ } while (0);
+
+ Dll_PopTlsNameBuffer(TlsData);
+}
+
+
+//---------------------------------------------------------------------------
+// File_DoAutoRecover
+//---------------------------------------------------------------------------
+
+
+_FX void File_DoAutoRecover(BOOLEAN force)
+{
+ static ULONG last_ticks = 0;
+
+ ULONG LastError;
+ THREAD_DATA *TlsData = Dll_GetTlsData(&LastError);
+
+ ULONG ticks = GetTickCount();
+ if (force || (ticks - last_ticks > 400)) {
+
+ last_ticks = ticks;
+
+ if (TryEnterCriticalSection(&File_RecHandles_CritSec)) {
+
+ if (List_Head(&File_RecPaths)) {
+
+ Dll_PushTlsNameBuffer(TlsData);
+
+ File_DoAutoRecover_2(force, ticks);
+
+ Dll_PopTlsNameBuffer(TlsData);
+ }
+
+ LeaveCriticalSection(&File_RecHandles_CritSec);
+ }
+ }
+
+ SetLastError(LastError);
+}
+
+
+//---------------------------------------------------------------------------
+// File_DoAutoRecover_2
+//---------------------------------------------------------------------------
+
+
+_FX void File_DoAutoRecover_2(BOOLEAN force, ULONG ticks)
+{
+ NTSTATUS status;
+ SYSTEM_HANDLE_INFORMATION *info = NULL;
+ FILE_GET_ALL_HANDLES_RPL *rpl = NULL;
+ ULONG info_len = 64, len, i;
+ WCHAR *pathbuf;
+ ULONG UseCount = 0;
+ FILE_RECOVER_FOLDER *rec;
+ UCHAR FileObjectTypeNumber = 0;
+
+ //
+ // get list of open handles in the system
+ //
+
+ for (i = 0; i < 5; ++i) {
+
+ info = Dll_AllocTemp(info_len);
+
+ status = NtQuerySystemInformation(
+ SystemHandleInformation, info, info_len, &len);
+
+ if (NT_SUCCESS(status))
+ break;
+
+ Dll_Free(info);
+ info_len = len + 64;
+
+ if (status == STATUS_BUFFER_OVERFLOW ||
+ status == STATUS_INFO_LENGTH_MISMATCH ||
+ status == STATUS_BUFFER_TOO_SMALL) {
+
+ continue;
+ }
+
+ break;
+ }
+
+ if (!Dll_CompartmentMode) // NoServiceAssist // don't try that in app mode, we had a proepr token
+ if (status == STATUS_ACCESS_DENIED) {
+
+ //
+ // on Windows 8.1, NtQuerySystemInformation fails, probably because
+ // we are running without any privileges, so go through SbieSvc
+ //
+
+ MSG_HEADER req;
+ req.length = sizeof(req);
+ req.msgid = MSGID_FILE_GET_ALL_HANDLES;
+ rpl = (FILE_GET_ALL_HANDLES_RPL *)SbieDll_CallServer(&req);
+
+ if (rpl) {
+ info = NULL;
+ status = STATUS_SUCCESS;
+ }
+ }
+
+ if (! NT_SUCCESS(status))
+ return;
+
+ pathbuf = Dll_AllocTemp(1024);
+
+ //
+ // scan list of queued recovery files
+ //
+
+ rec = List_Head(&File_RecPaths);
+ while (rec) {
+
+ FILE_RECOVER_FOLDER *rec_next = List_Next(rec);
+ BOOLEAN send2199 = FALSE;
+
+ if (force)
+ send2199 = TRUE;
+ else {
+ if (ticks - rec->ticks >= 1000) {
+ ULONG UseCount = File_DoAutoRecover_3(
+ rec->path, pathbuf, info, rpl, &FileObjectTypeNumber);
+ if (UseCount == 0)
+ send2199 = TRUE;
+ }
+ }
+
+ if (send2199) {
+ WCHAR *colon = wcschr(rec->path, L':');
+ if (!colon) {
+
+ UNICODE_STRING uni;
+ WCHAR *TruePath, *CopyPath;
+ RtlInitUnicodeString(&uni, rec->path);
+ status = File_GetName(NULL, &uni, &TruePath, &CopyPath, NULL);
+
+ const WCHAR* strings[] = { Dll_BoxName, rec->path, CopyPath, NULL };
+ SbieApi_LogMsgExt(2199, strings);
+ }
+ List_Remove(&File_RecPaths, rec);
+ }
+
+ rec = rec_next;
+ }
+
+ //
+ // finish
+ //
+
+ Dll_Free(pathbuf);
+ if (info)
+ Dll_Free(info);
+ if (rpl)
+ Dll_Free(rpl);
+}
+
+
+//---------------------------------------------------------------------------
+// File_DoAutoRecover_3
+//---------------------------------------------------------------------------
+
+
+_FX ULONG File_DoAutoRecover_3(
+ const WCHAR *PathToFind, WCHAR *PathBuf1024,
+ SYSTEM_HANDLE_INFORMATION *info, FILE_GET_ALL_HANDLES_RPL *rpl,
+ UCHAR *FileObjectTypeNumber)
+{
+ HANDLE FileHandle;
+ ULONG UseCount, i;
+
+ //
+ // scan handles for current process
+ //
+
+ UseCount = 0;
+
+ if (info) {
+
+ for (i = 0; i < info->Count; ++i) {
+
+ HANDLE_INFO *hi = &info->HandleInfo[i];
+
+ if (hi->ProcessId != Dll_ProcessId)
+ continue;
+
+ FileHandle = (HANDLE)(ULONG_PTR)hi->Handle;
+
+ UseCount += File_DoAutoRecover_4(
+ PathToFind, PathBuf1024,
+ FileHandle, hi->ObjectTypeNumber, FileObjectTypeNumber);
+ }
+
+ } else if (rpl) {
+
+ for (i = 0; i < rpl->num_handles; ++i) {
+
+ UCHAR objtype = (UCHAR)(rpl->handles[i] >> 24);
+
+ FileHandle = (HANDLE)(ULONG_PTR)(rpl->handles[i] & 0x00FFFFFFU);
+
+ UseCount += File_DoAutoRecover_4(
+ PathToFind, PathBuf1024,
+ FileHandle, objtype, FileObjectTypeNumber);
+ }
+ }
+
+ return UseCount;
+}
+
+
+//---------------------------------------------------------------------------
+// File_DoAutoRecover_4
+//---------------------------------------------------------------------------
+
+
+_FX ULONG File_DoAutoRecover_4(
+ const WCHAR *PathToFind, WCHAR *PathBuf1024,
+ HANDLE FileHandle, UCHAR ObjectTypeNumber, UCHAR *FileObjectTypeNumber)
+{
+ UNICODE_STRING uni;
+ WCHAR *TruePath, *CopyPath;
+ NTSTATUS status;
+
+ //
+ // make sure the handle is to a file
+ //
+
+ if (*FileObjectTypeNumber) {
+
+ if (ObjectTypeNumber != *FileObjectTypeNumber)
+ return 0;
+
+ } else {
+
+ if (Obj_GetObjectType(FileHandle) == OBJ_TYPE_FILE) {
+
+ *FileObjectTypeNumber = ObjectTypeNumber;
+
+ } else
+ return 0;
+ }
+
+ //
+ // get file name
+ //
+
+ status = File_GetFileName(FileHandle, 1000, PathBuf1024);
+ if (! NT_SUCCESS(status))
+ return 0;
+
+ RtlInitUnicodeString(&uni, PathBuf1024);
+ status = File_GetName(NULL, &uni, &TruePath, &CopyPath, NULL);
+ if (! NT_SUCCESS(status))
+ return 0;
+
+ if (_wcsicmp(PathToFind, TruePath) == 0)
+ return 1;
+
+ return 0;
+}
+
+
+//---------------------------------------------------------------------------
+// File_MsoDll
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN File_MsoDll(HMODULE module)
+{
+ //
+ // hack for File_IsRecoverable
+ //
+
+ File_MsoDllLoaded = TRUE;
+ return TRUE;
+}
\ No newline at end of file
diff --git a/Sandboxie/core/dll/file_snapshots.c b/Sandboxie/core/dll/file_snapshots.c
new file mode 100644
index 00000000..237942ff
--- /dev/null
+++ b/Sandboxie/core/dll/file_snapshots.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright 2020-2022 David Xanatos, xanasoft.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+//---------------------------------------------------------------------------
+// File (Snapshot)
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#define FILE_MAX_SNAPSHOT_ID 17
+
+#define FILE_INSNAPSHOT_FLAG 0x0004
+
+//---------------------------------------------------------------------------
+// Structures and Types
+//---------------------------------------------------------------------------
+
+
+typedef struct _FILE_SNAPSHOT {
+ WCHAR ID[FILE_MAX_SNAPSHOT_ID];
+ ULONG IDlen;
+ ULONG ScramKey;
+ //WCHAR Name[34];
+ struct _FILE_SNAPSHOT* Parent;
+ LIST PathRoot;
+} FILE_SNAPSHOT, *PFILE_SNAPSHOT;
+
+
+//---------------------------------------------------------------------------
+// Variables
+//---------------------------------------------------------------------------
+
+
+static const WCHAR* File_Snapshot_Prefix = L"snapshot-";
+static const ULONG File_Snapshot_PrefixLen = 9; // wcslen(File_Snapshot_Prefix);
+
+
+static FILE_SNAPSHOT *File_Snapshot = NULL;
+static ULONG File_Snapshot_Count = 0;
+
+
+
+//---------------------------------------------------------------------------
+// Functions
+//---------------------------------------------------------------------------
+
+static void File_ScrambleShortName(WCHAR* ShortName, CCHAR* ShortNameLength, ULONG ScramKey);
+static void File_UnScrambleShortName(WCHAR* ShortName, ULONG ScramKey);
+
+static WCHAR* File_MakeSnapshotPath(FILE_SNAPSHOT* Cur_Snapshot, const WCHAR* CopyPath);
+static WCHAR* File_FindSnapshotPath(WCHAR* CopyPath);
+static WCHAR* File_ResolveTruePath(WCHAR* TruePath, WCHAR* CopyPath, ULONG* pFlags);
+static ULONG File_IsDeletedEx(const WCHAR* TruePath, const WCHAR* CopyPath, FILE_SNAPSHOT* snapshot);
+
+
+static void File_InitSnapshots(void);
+
+//---------------------------------------------------------------------------
+// File_Scramble_Char
+//---------------------------------------------------------------------------
+
+
+_FX WCHAR File_Scramble_Char(WCHAR wValue, int Key, BOOLEAN scram)
+{
+ //
+ // This function allows to scramble file name charakters properly,
+ // i.e. no invalid cahacters can result fron this operation.
+ // It does not scramble invalid charakters like: " * / : < > ? \ |
+ // And it does not scramble ~
+ // The entropy of the scrambler is 25,5bit (i.e. 52 million values)
+ //
+
+ char reserved_ch[] = { '\"', '*', '/', ':', '<', '>', '?', '\\', '|' };
+ const int reserved_count = 9;
+ const int max_ch = 0x7E - reserved_count - 0x20;
+
+ int uValue = (wValue & 0x7F);
+ if (uValue < 0x20 || uValue >= 0x7E) // < space || >= ~
+ return wValue;
+ for (int i = 0; i < reserved_count; i++)
+ if (uValue == reserved_ch[i]) return wValue;
+
+ Key &= 0x7f;
+ while (Key >= max_ch)
+ Key -= max_ch;
+ if (!scram)
+ Key = -Key;
+
+ for (int i = 1; i <= reserved_count; i++)
+ if (uValue > reserved_ch[reserved_count - i]) uValue -= 1;
+ uValue -= 0x20;
+
+ uValue += Key;
+
+ if (uValue >= max_ch)
+ uValue -= max_ch;
+ else if (uValue < 0)
+ uValue += max_ch;
+
+ uValue += 0x20;
+ for (int i = 0; i < reserved_count; i++)
+ if (uValue >= reserved_ch[i]) uValue += 1;
+
+ return uValue;
+}
+
+
+//---------------------------------------------------------------------------
+// File_ScrambleShortName
+//---------------------------------------------------------------------------
+
+
+_FX void File_ScrambleShortName(WCHAR* ShortName, CCHAR* ShortNameBytes, ULONG ScramKey)
+{
+ CCHAR ShortNameLength = *ShortNameBytes / sizeof(WCHAR);
+
+ CCHAR dot_pos;
+ WCHAR *dot = wcsrchr(ShortName, L'.');
+ if (dot == NULL) {
+ dot_pos = ShortNameLength;
+ if (ShortNameLength >= 12)
+ return; // this should never not happen!
+ ShortName[ShortNameLength++] = L'.';
+ }
+ else
+ dot_pos = (CCHAR)(dot - ShortName);
+
+ while (ShortNameLength - dot_pos < 4)
+ {
+ if (ShortNameLength >= 12)
+ return; // this should never not happen!
+ ShortName[ShortNameLength++] = L' ';
+ }
+
+ *ShortNameBytes = ShortNameLength * sizeof(WCHAR);
+
+ if (dot_pos > 0)
+ ShortName[dot_pos - 1] = File_Scramble_Char(ShortName[dot_pos - 1], ((char*)&ScramKey)[0], TRUE);
+ for (int i = 1; i <= 3; i++)
+ ShortName[dot_pos + i] = File_Scramble_Char(ShortName[dot_pos + i], ((char*)&ScramKey)[i], TRUE);
+}
+
+
+//---------------------------------------------------------------------------
+// File_UnScrambleShortName
+//---------------------------------------------------------------------------
+
+
+_FX void File_UnScrambleShortName(WCHAR* ShortName, ULONG ScramKey)
+{
+ CCHAR ShortNameLength = (CCHAR)wcslen(ShortName);
+
+ WCHAR *dot = wcsrchr(ShortName, L'.');
+ if (dot == NULL)
+ return; // not a scrambled short name.
+ CCHAR dot_pos = (CCHAR)(dot - ShortName);
+
+ if (dot_pos > 0)
+ ShortName[dot_pos - 1] = File_Scramble_Char(ShortName[dot_pos - 1], ((char*)&ScramKey)[0], FALSE);
+ for (int i = 1; i <= 3; i++)
+ ShortName[dot_pos + i] = File_Scramble_Char(ShortName[dot_pos + i], ((char*)&ScramKey)[i], FALSE);
+
+ while (ShortName[ShortNameLength - 1] == L' ')
+ ShortName[ShortNameLength-- - 1] = 0;
+ if (ShortName[ShortNameLength - 1] == L'.')
+ ShortName[ShortNameLength-- - 1] = 0;
+}
+
+
+//---------------------------------------------------------------------------
+// File_MakeSnapshotPath
+//---------------------------------------------------------------------------
+
+
+_FX WCHAR* File_MakeSnapshotPath(FILE_SNAPSHOT* Cur_Snapshot, const WCHAR* CopyPath)
+{
+ if (!Cur_Snapshot)
+ return NULL;
+
+ ULONG prefixLen = File_FindBoxPrefixLength(CopyPath);
+ if (prefixLen == 0)
+ return NULL;
+
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ WCHAR* TmplName = Dll_GetTlsNameBuffer(TlsData, TMPL_NAME_BUFFER, (wcslen(CopyPath) + File_Snapshot_PrefixLen + FILE_MAX_SNAPSHOT_ID + 1) * sizeof(WCHAR));
+
+ wcsncpy(TmplName, CopyPath, prefixLen + 1);
+ wcscpy(TmplName + prefixLen + 1, File_Snapshot_Prefix);
+ wcscpy(TmplName + prefixLen + 1 + File_Snapshot_PrefixLen, Cur_Snapshot->ID);
+ wcscpy(TmplName + prefixLen + 1 + File_Snapshot_PrefixLen + Cur_Snapshot->IDlen, CopyPath + prefixLen);
+
+ return TmplName;
+}
+
+
+//---------------------------------------------------------------------------
+// File_FindSnapshotPath
+//---------------------------------------------------------------------------
+
+
+_FX WCHAR* File_FindSnapshotPath(WCHAR* CopyPath)
+{
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES objattrs;
+ UNICODE_STRING objname;
+ ULONG FileType;
+
+ InitializeObjectAttributes(&objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ //
+ // When working with snapshots the actual "CopyFile" may be located in a snapshot directory.
+ // To deal with that when the file is not in the active box directory we look through the snapshots,
+ // When we find it we update the path to point to the snapshot containing the file.
+ //
+
+ RtlInitUnicodeString(&objname, CopyPath);
+ status = File_GetFileType(&objattrs, FALSE, &FileType, NULL);
+ if (!(status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND))
+ return NULL; // file is present directly in copy path
+
+ for (FILE_SNAPSHOT* Cur_Snapshot = File_Snapshot; Cur_Snapshot != NULL; Cur_Snapshot = Cur_Snapshot->Parent)
+ {
+ WCHAR* TmplName = File_MakeSnapshotPath(Cur_Snapshot, CopyPath);
+ if (!TmplName)
+ break;
+
+ RtlInitUnicodeString(&objname, TmplName);
+ status = File_GetFileType(&objattrs, FALSE, &FileType, NULL);
+ if (!(status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND))
+ {
+ return TmplName;
+ }
+ }
+
+ return NULL; // this file is not in any snapshot
+}
+
+
+//---------------------------------------------------------------------------
+// File_GetPathFlagsEx
+//---------------------------------------------------------------------------
+
+
+_FX ULONG File_GetPathFlagsEx(const WCHAR *TruePath, const WCHAR *CopyPath, WCHAR** pRelocation, FILE_SNAPSHOT* lastSnapshot)
+{
+ ULONG Flags = 0;
+ WCHAR* Relocation = NULL;
+
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ //
+ // this function handles the Delete V2 as well as with snapshots
+ //
+
+ if (File_Delete_v2) {
+
+ //
+ // check true path relocation and deleteion for the active state
+ //
+
+ Relocation = NULL;
+ Flags = File_GetPathFlags(TruePath, &Relocation);
+ if (FILE_PATH_DELETED(Flags))
+ goto finish;
+
+ if (Relocation) {
+
+ if (!File_Snapshot)
+ goto finish; // take a shortcut
+
+ TruePath = Dll_GetTlsNameBuffer(TlsData, TRUE_NAME_BUFFER, wcslen(Relocation));
+ wcscpy((WCHAR*)TruePath, Relocation);
+ }
+ }
+
+ if (File_Snapshot != NULL) {
+
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES objattrs;
+ UNICODE_STRING objname;
+ ULONG FileType;
+
+ InitializeObjectAttributes(&objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ for (FILE_SNAPSHOT* Cur_Snapshot = File_Snapshot; Cur_Snapshot != lastSnapshot; Cur_Snapshot = Cur_Snapshot->Parent)
+ {
+ if (CopyPath) {
+
+ //
+ // check if the specified file is present in the current snapshot
+ //
+
+ WCHAR* TmplName = File_MakeSnapshotPath(Cur_Snapshot, CopyPath);
+ if (!TmplName)
+ break; // something went wrong
+
+ RtlInitUnicodeString(&objname, TmplName);
+ status = File_GetFileType(&objattrs, FALSE, &FileType, NULL);
+ if (!(status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND)) {
+
+ Flags |= FILE_INSNAPSHOT_FLAG;
+ Relocation = TmplName;
+ goto finish;
+ }
+ }
+
+ if (File_Delete_v2) {
+
+ //
+ // check true path relocation and deleteion for the current snapshot
+ //
+
+ Flags = File_GetPathFlags_internal(&Cur_Snapshot->PathRoot, TruePath, &Relocation, TRUE);
+ if (FILE_PATH_DELETED(Flags))
+ goto finish;
+
+ if (Relocation) {
+
+ if (!Cur_Snapshot->Parent)
+ break; // take a shortcut
+
+ TruePath = Dll_GetTlsNameBuffer(TlsData, TRUE_NAME_BUFFER, (wcslen(Relocation) + 1) * sizeof(WCHAR));
+ wcscpy((WCHAR*)TruePath, Relocation);
+
+ if (!CopyPath)
+ continue;
+
+ //
+ // update the copy file name
+ //
+
+ Dll_PushTlsNameBuffer(TlsData);
+
+ WCHAR* TruePath2, *CopyPath2;
+ RtlInitUnicodeString(&objname, Relocation);
+ File_GetName(NULL, &objname, &TruePath2, &CopyPath2, NULL);
+
+ Dll_PopTlsNameBuffer(TlsData);
+
+ // note: pop leaves TruePath2 valid we can still use it
+
+ CopyPath = Dll_GetTlsNameBuffer(TlsData, COPY_NAME_BUFFER, (wcslen(CopyPath2) + 1) * sizeof(WCHAR));
+ wcscpy((WCHAR*)CopyPath, CopyPath2);
+ }
+ }
+ }
+ }
+
+finish:
+
+ if (pRelocation) *pRelocation = Relocation; // can be template buffer or move buffer
+ return Flags;
+}
+
+
+//---------------------------------------------------------------------------
+// File_ResolveTruePath
+//---------------------------------------------------------------------------
+
+
+_FX WCHAR* File_ResolveTruePath(WCHAR *TruePath, WCHAR *CopyPath, ULONG* pFlags)
+{
+ WCHAR* Relocation = NULL;
+ ULONG Flags = File_GetPathFlagsEx(TruePath, CopyPath, &Relocation, NULL);
+
+ if (pFlags) *pFlags = Flags;
+ return Relocation;
+}
+
+
+//---------------------------------------------------------------------------
+// File_IsDeletedEx
+//---------------------------------------------------------------------------
+
+
+_FX ULONG File_IsDeletedEx(const WCHAR* TruePath, const WCHAR* CopyPath, FILE_SNAPSHOT* snapshot)
+{
+ ULONG Flags = File_GetPathFlagsEx(TruePath, CopyPath, NULL, snapshot);
+
+ return (Flags & FILE_DELETED_MASK);
+}
+
+
+//---------------------------------------------------------------------------
+// File_InitSnapshots
+//---------------------------------------------------------------------------
+
+// CRC
+#define CRC_WITH_ADLERTZUK64
+#include "common/crc.c"
+
+_FX void File_InitSnapshots(void)
+{
+ WCHAR ShapshotsIni[MAX_PATH] = { 0 };
+ wcscpy(ShapshotsIni, Dll_BoxFilePath);
+ wcscat(ShapshotsIni, L"\\Snapshots.ini");
+ SbieDll_TranslateNtToDosPath(ShapshotsIni);
+
+ WCHAR Shapshot[FILE_MAX_SNAPSHOT_ID] = { 0 };
+ GetPrivateProfileStringW(L"Current", L"Snapshot", L"", Shapshot, FILE_MAX_SNAPSHOT_ID, ShapshotsIni);
+
+ if (*Shapshot == 0)
+ return; // not using snapshots
+
+ File_Snapshot = Dll_Alloc(sizeof(FILE_SNAPSHOT));
+ memzero(File_Snapshot, sizeof(FILE_SNAPSHOT));
+ wcscpy(File_Snapshot->ID, Shapshot);
+ File_Snapshot->IDlen = wcslen(Shapshot);
+ FILE_SNAPSHOT* Cur_Snapshot = File_Snapshot;
+ File_Snapshot_Count = 1;
+
+ for (;;)
+ {
+ Cur_Snapshot->ScramKey = CRC32(Cur_Snapshot->ID, Cur_Snapshot->IDlen * sizeof(WCHAR));
+
+ WCHAR ShapshotId[26] = L"Snapshot_";
+ wcscat(ShapshotId, Shapshot);
+
+ if (File_Delete_v2) {
+
+ WCHAR PathFile[MAX_PATH];
+ wcscpy(PathFile, File_Snapshot_Prefix);
+ wcscat(PathFile, Cur_Snapshot->ID);
+ wcscat(PathFile, L"\\");
+ wcscat(PathFile, FILE_PATH_FILE_NAME);
+
+ File_LoadPathTree_internal(&Cur_Snapshot->PathRoot, PathFile);
+ }
+
+ //WCHAR ShapshotName[34] = { 0 };
+ //GetPrivateProfileStringW(ShapshotId, L"Name", L"", ShapshotName, 34, ShapshotsIni);
+ //wcscpy(Cur_Snapshot->Name, ShapshotName);
+
+ GetPrivateProfileStringW(ShapshotId, L"Parent", L"", Shapshot, 16, ShapshotsIni);
+
+ if (*Shapshot == 0)
+ break; // no more snapshots
+
+ Cur_Snapshot->Parent = Dll_Alloc(sizeof(FILE_SNAPSHOT));
+ memzero(Cur_Snapshot->Parent, sizeof(FILE_SNAPSHOT));
+ wcscpy(Cur_Snapshot->Parent->ID, Shapshot);
+ Cur_Snapshot->Parent->IDlen = wcslen(Shapshot);
+ Cur_Snapshot = Cur_Snapshot->Parent;
+ File_Snapshot_Count++;
+ }
+}
diff --git a/Sandboxie/core/dll/handle.c b/Sandboxie/core/dll/handle.c
new file mode 100644
index 00000000..a81d4d16
--- /dev/null
+++ b/Sandboxie/core/dll/handle.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2021-2022 David Xanatos, xanasoft.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+//---------------------------------------------------------------------------
+// Handle
+//---------------------------------------------------------------------------
+
+#define NOGDI
+#include "dll.h"
+#include "handle.h"
+#include
+#include "debug.h"
+
+#include "common/pool.h"
+#include "common/map.h"
+
+
+//---------------------------------------------------------------------------
+// Structures and Types
+//---------------------------------------------------------------------------
+
+typedef struct _HANDLE_STATE {
+
+ BOOLEAN DeleteOnClose;
+ P_CloseHandler CloseHandlers[MAX_CLOSE_HANDLERS];
+ WCHAR* RelocationPath;
+
+} HANDLE_STATE;
+
+
+//---------------------------------------------------------------------------
+// Variables
+//---------------------------------------------------------------------------
+
+extern POOL* Dll_Pool;
+
+static HASH_MAP Handle_StatusData;
+static CRITICAL_SECTION Handle_StatusData_CritSec;
+
+
+//---------------------------------------------------------------------------
+// Functions
+//---------------------------------------------------------------------------
+
+
+
+//---------------------------------------------------------------------------
+// Handle_Init
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN Handle_Init(void)
+{
+ InitializeCriticalSection(&Handle_StatusData_CritSec);
+ map_init(&Handle_StatusData, Dll_Pool);
+
+ return TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+// Handle_SetDeleteOnClose
+//---------------------------------------------------------------------------
+
+
+_FX VOID Handle_SetDeleteOnClose(HANDLE FileHandle, BOOLEAN DeleteOnClose)
+{
+ EnterCriticalSection(&Handle_StatusData_CritSec);
+
+ HANDLE_STATE* state = map_get(&Handle_StatusData, FileHandle);
+ if (!state) {
+ state = map_insert(&Handle_StatusData, FileHandle, NULL, sizeof(HANDLE_STATE));
+ }
+
+ state->DeleteOnClose = DeleteOnClose;
+
+ LeaveCriticalSection(&Handle_StatusData_CritSec);
+}
+
+
+//---------------------------------------------------------------------------
+// Handle_SetRelocationPath
+//---------------------------------------------------------------------------
+
+
+_FX VOID Handle_SetRelocationPath(HANDLE FileHandle, WCHAR* RelocationPath)
+{
+ EnterCriticalSection(&Handle_StatusData_CritSec);
+
+ HANDLE_STATE* state = map_get(&Handle_StatusData, FileHandle);
+ if (!state) { // this shoudl always be the case, as we only use Handle_SetRelocationPath when the handle is first created
+ state = map_insert(&Handle_StatusData, FileHandle, NULL, sizeof(HANDLE_STATE));
+ } else if (state->RelocationPath) Dll_Free(state->RelocationPath); // should not happen but in case
+
+ state->RelocationPath = Dll_Alloc((wcslen(RelocationPath) + 1) * sizeof(WCHAR));
+ wcscpy(state->RelocationPath, RelocationPath);
+
+ LeaveCriticalSection(&Handle_StatusData_CritSec);
+}
+
+
+//---------------------------------------------------------------------------
+// Handle_GetRelocationPath
+//---------------------------------------------------------------------------
+
+
+_FX WCHAR* Handle_GetRelocationPath(HANDLE FileHandle, ULONG ExtraLength)
+{
+ WCHAR* name = NULL;
+
+ EnterCriticalSection(&Handle_StatusData_CritSec);
+
+ HANDLE_STATE* state = map_get(&Handle_StatusData, FileHandle);
+ if (state && state->RelocationPath) {
+
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ ULONG length = (wcslen(state->RelocationPath) + 1) * sizeof(WCHAR);
+ name = Dll_GetTlsNameBuffer(TlsData, TRUE_NAME_BUFFER, length + ExtraLength);
+ wcscpy(name, state->RelocationPath);
+ }
+
+ LeaveCriticalSection(&Handle_StatusData_CritSec);
+
+ return name;
+}
+
+
+//---------------------------------------------------------------------------
+// Handle_FreeCloseHandler
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN Handle_FreeCloseHandler(HANDLE FileHandle, P_CloseHandler* CloseHandlers, BOOLEAN* DeleteOnClose)
+{
+ BOOLEAN HasCloseHandlers = FALSE;
+
+ EnterCriticalSection(&Handle_StatusData_CritSec);
+
+ HANDLE_STATE* state = (HANDLE_STATE*)map_get(&Handle_StatusData, FileHandle);
+ if (state) {
+
+ HasCloseHandlers = TRUE;
+
+ if(CloseHandlers)
+ memcpy(CloseHandlers, state->CloseHandlers, MAX_CLOSE_HANDLERS * sizeof(P_CloseHandler));
+ if(DeleteOnClose) *DeleteOnClose = state->DeleteOnClose;
+
+ if (state->RelocationPath) Dll_Free(state->RelocationPath);
+ }
+
+ map_remove(&Handle_StatusData, FileHandle);
+
+ LeaveCriticalSection(&Handle_StatusData_CritSec);
+
+ return HasCloseHandlers;
+}
+
+
+//---------------------------------------------------------------------------
+// Handle_RegisterCloseHandler
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN Handle_RegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler)
+{
+ if (!FileHandle || FileHandle == (HANDLE)-1)
+ return FALSE;
+
+ ULONG i;
+
+ EnterCriticalSection(&Handle_StatusData_CritSec);
+
+ HANDLE_STATE* state = map_get(&Handle_StatusData, FileHandle);
+ if (!state) {
+ state = map_insert(&Handle_StatusData, FileHandle, NULL, sizeof(HANDLE_STATE));
+ }
+
+ for (i = 0; i < MAX_CLOSE_HANDLERS; i++) {
+ if (state->CloseHandlers[i] == CloseHandler)
+ break; // already registered
+ if (state->CloseHandlers[i] == NULL) {
+ state->CloseHandlers[i] = CloseHandler; // set to empty slot
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&Handle_StatusData_CritSec);
+
+ if (i == MAX_CLOSE_HANDLERS) {
+ SbieApi_Log(2301, L"No free CloseHandlers slot available");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+// Handle_UnRegisterCloseHandler
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN Handle_UnRegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler)
+{
+ ULONG i = MAX_CLOSE_HANDLERS;
+
+ EnterCriticalSection(&Handle_StatusData_CritSec);
+
+ HANDLE_STATE* state = map_get(&Handle_StatusData, FileHandle);
+ if (state) {
+
+ for (i = 0; i < MAX_CLOSE_HANDLERS; i++) {
+ if (state->CloseHandlers[i] == CloseHandler) {
+ state->CloseHandlers[i] = NULL; // clear slot
+ break;
+ }
+ }
+ }
+
+ LeaveCriticalSection(&Handle_StatusData_CritSec);
+
+ return i != MAX_CLOSE_HANDLERS;
+}
+
+
+//---------------------------------------------------------------------------
+// Handle_SetupDuplicate
+//---------------------------------------------------------------------------
+
+
+_FX void Handle_SetupDuplicate(HANDLE OldFileHandle, HANDLE NewFileHandle)
+{
+ ULONG i;
+
+ EnterCriticalSection(&Handle_StatusData_CritSec);
+
+ HANDLE_STATE* state = map_get(&Handle_StatusData, OldFileHandle);
+ if (state) {
+
+ if(state->RelocationPath)
+ Handle_SetRelocationPath(NewFileHandle, state->RelocationPath);
+
+ // todo: add a flag to each CloseHandlers entry to indicate if it should be propagated or not
+ BOOLEAN found = FALSE;
+ for (i = 0; i < MAX_CLOSE_HANDLERS; i++) {
+ if (state->CloseHandlers[i] == File_NotifyRecover) {
+ found = TRUE;
+ break;
+ }
+ }
+ if(found)
+ Handle_RegisterCloseHandler(NewFileHandle, File_NotifyRecover);
+ }
+
+ LeaveCriticalSection(&Handle_StatusData_CritSec);
+}
diff --git a/Sandboxie/core/dll/handle.h b/Sandboxie/core/dll/handle.h
new file mode 100644
index 00000000..261aafbf
--- /dev/null
+++ b/Sandboxie/core/dll/handle.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021-2022 David Xanatos, xanasoft.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+#ifndef _MY_HANDLE_H
+#define _MY_HANDLE_H
+
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#define MAX_CLOSE_HANDLERS 4
+
+
+//---------------------------------------------------------------------------
+// Functions
+//---------------------------------------------------------------------------
+
+
+typedef void(*P_CloseHandler)(HANDLE handle);
+
+VOID Handle_SetDeleteOnClose(HANDLE FileHandle, BOOLEAN DeleteOnClose);
+
+BOOLEAN Handle_RegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler);
+
+BOOLEAN Handle_UnRegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler);
+
+VOID Handle_SetRelocationPath(HANDLE FileHandle, WCHAR* RelocationPath);
+
+WCHAR* Handle_GetRelocationPath(HANDLE FileHandle, ULONG ExtraLength);
+
+BOOLEAN Handle_FreeCloseHandler(HANDLE FileHandle, P_CloseHandler* CloseHandlers, BOOLEAN* DeleteOnClose);
+
+
+//---------------------------------------------------------------------------
+
+
+#endif /* _MY_HANDLE_H */
diff --git a/Sandboxie/core/dll/ipc.c b/Sandboxie/core/dll/ipc.c
index 42723ac9..7f895e53 100644
--- a/Sandboxie/core/dll/ipc.c
+++ b/Sandboxie/core/dll/ipc.c
@@ -379,6 +379,7 @@ _FX BOOLEAN Ipc_Init(void)
SBIEDLL_HOOK(Ipc_, NtImpersonateThread);
}
+ //if (!Dll_AlernateIpcNaming) // alternate naming does not need an own namespace
Ipc_CreateObjects();
List_Init(&Ipc_DynamicPortNames);
@@ -525,6 +526,21 @@ _FX NTSTATUS Ipc_GetName(
if (ObjectName) {
objname_len = ObjectName->Length & ~1;
objname_buf = ObjectName->Buffer;
+
+ //if (Dll_AlernateIpcNaming) {
+ //
+ // //
+ // // Since in this mode we don't call Ipc_CreateObjects we dont have a boxed namespace
+ // // and are using existing namespaces only with a name suffix
+ // // hence we can't use Global without system provileges, so we strip it
+ // //
+ //
+ // if (_wcsnicmp(objname_buf, L"Global\\", 7) == 0) {
+ // objname_len -= 7;
+ // objname_buf += 7;
+ // }
+ //}
+
} else {
objname_len = 0;
objname_buf = NULL;
@@ -665,6 +681,21 @@ _FX NTSTATUS Ipc_GetName(
check_sandbox_prefix:
+ //if (Dll_AlernateIpcNaming)
+ //{
+ // if (length >= Dll_BoxIpcPathLen &&
+ // 0 == Dll_NlsStrCmp(
+ // &(*OutTruePath)[length - Dll_BoxIpcPathLen], Dll_BoxIpcPath, Dll_BoxIpcPathLen))
+ // {
+ // (*OutTruePath)[length - Dll_BoxIpcPathLen] = L'\0';
+ // length -= Dll_BoxIpcPathLen;
+ // if (OutIsBoxedPath)
+ // *OutIsBoxedPath = TRUE;
+ //
+ // goto check_sandbox_prefix;
+ // }
+ //}
+ //else
if (length >= Dll_BoxIpcPathLen &&
0 == Dll_NlsStrCmp(
*OutTruePath, Dll_BoxIpcPath, Dll_BoxIpcPathLen))
@@ -688,11 +719,23 @@ check_sandbox_prefix:
*OutCopyPath = name;
- wmemcpy(name, Dll_BoxIpcPath, Dll_BoxIpcPathLen);
- name += Dll_BoxIpcPathLen;
+ //if (Dll_AlernateIpcNaming)
+ //{
+ // wmemcpy(name, *OutTruePath, length);
+ // name += length;
+ //
+ // wmemcpy(name, Dll_BoxIpcPath, Dll_BoxIpcPathLen);
+ // name += Dll_BoxIpcPathLen;
+ //}
+ //else
+ {
+ wmemcpy(name, Dll_BoxIpcPath, Dll_BoxIpcPathLen);
+ name += Dll_BoxIpcPathLen;
+
+ wmemcpy(name, *OutTruePath, length);
+ name += length;
+ }
- wmemcpy(name, *OutTruePath, length);
- name += length;
*name = L'\0';
//
@@ -883,6 +926,9 @@ _FX NTSTATUS Ipc_CreatePath(WCHAR *TruePath, WCHAR *CopyPath)
UNICODE_STRING objname;
WCHAR *backslash;
+ //if (Dll_AlernateIpcNaming)
+ // return STATUS_OBJECT_PATH_NOT_FOUND;
+
//
// open the TruePath object directory containing the object
// for which we got STATUS_OBJECT_PATH_NOT_FOUND
@@ -3730,6 +3776,20 @@ _FX ULONG Ipc_NtQueryObjectName(UNICODE_STRING *ObjectName, ULONG MaxLen)
ULONG Len = ObjectName->Length;
WCHAR *Buf = ObjectName->Buffer;
+ //if (Dll_AlernateIpcNaming)
+ //{
+ // if (Len >= Dll_BoxIpcPathLen * sizeof(WCHAR) &&
+ // 0 == Dll_NlsStrCmp(&Buf[Len - Dll_BoxIpcPathLen], Dll_BoxIpcPath, Dll_BoxIpcPathLen)) {
+ //
+ // Buf[Len - Dll_BoxIpcPathLen] = L'\0';
+ //
+ // ObjectName->Length -= (USHORT)Dll_BoxIpcPathLen;
+ // ObjectName->MaximumLength = ObjectName->Length + sizeof(WCHAR);
+ //
+ // return ObjectName->MaximumLength;
+ // }
+ //}
+ //else
if (Len >= Dll_BoxIpcPathLen * sizeof(WCHAR) &&
0 == Dll_NlsStrCmp(Buf, Dll_BoxIpcPath, Dll_BoxIpcPathLen)) {
diff --git a/Sandboxie/core/dll/key.c b/Sandboxie/core/dll/key.c
index d735fb2f..cef0bc83 100644
--- a/Sandboxie/core/dll/key.c
+++ b/Sandboxie/core/dll/key.c
@@ -23,10 +23,11 @@
#include "dll.h"
#include "obj.h"
+#include "handle.h"
#include "core/svc/FileWire.h"
#include "core/drv/api_defs.h"
#include
-
+#include "debug.h"
//---------------------------------------------------------------------------
// Defines
@@ -305,6 +306,8 @@ static const WCHAR *Key_Wow6432Node = L"\\Wow6432Node\\";
static BOOLEAN Key_UseObjectNames = FALSE;
+BOOLEAN Key_Delete_v2 = FALSE;
+
//---------------------------------------------------------------------------
// Debug Prints
//---------------------------------------------------------------------------
@@ -337,6 +340,7 @@ static BOOLEAN Key_UseObjectNames = FALSE;
//---------------------------------------------------------------------------
+#include "key_del.c"
#include "key_merge.c"
#include "key_util.c"
@@ -357,6 +361,8 @@ _FX BOOLEAN Key_Init(void)
Key_UseObjectNames = SbieApi_QueryConfBool(NULL, L"UseObjectNameForKeys", FALSE);
+ Key_Delete_v2 = SbieApi_QueryConfBool(NULL, L"UseRegDeleteV2", FALSE);
+
List_Init(&Key_Handles);
List_Init(&Key_MergeCacheList);
@@ -450,6 +456,16 @@ _FX NTSTATUS Key_GetName(
if (RootDirectory) {
+ name = Handle_GetRelocationPath(RootDirectory, objname_len);
+ if (name) {
+
+ *OutTruePath = name;
+
+ name = (*OutTruePath) + wcslen(*OutTruePath);
+
+ }
+ else {
+
length = 256;
name = Dll_GetTlsNameBuffer(
TlsData, TRUE_NAME_BUFFER, length + objname_len);
@@ -504,6 +520,8 @@ _FX NTSTATUS Key_GetName(
+ ((KEY_NAME_INFORMATION *)name)->NameLength / sizeof(WCHAR);
}
+ }
+
if (objname_len) {
*name = L'\\';
@@ -1095,6 +1113,41 @@ _FX NTSTATUS Key_NtCreateKey(
//---------------------------------------------------------------------------
+#ifdef WITH_DEBUG_
+static P_NtCreateKey __sys_NtCreateKey_ = NULL;
+
+_FX NTSTATUS Key_MyCreateKey(
+ HANDLE *KeyHandle,
+ ACCESS_MASK DesiredAccess,
+ OBJECT_ATTRIBUTES *ObjectAttributes,
+ ULONG TitleIndex,
+ UNICODE_STRING *Class,
+ ULONG CreateOptions,
+ ULONG *Disposition)
+{
+ ULONG Disposition_ = 0;
+
+ if (!Disposition)
+ Disposition = &Disposition_;
+
+ NTSTATUS status = __sys_NtCreateKey_(
+ KeyHandle, DesiredAccess, ObjectAttributes, TitleIndex,
+ Class, CreateOptions, Disposition);
+
+ if (*Disposition == REG_CREATED_NEW_KEY) {
+ while (! IsDebuggerPresent()) { OutputDebugString(L"BREAK\n"); Sleep(500); }
+ __debugbreak();
+ }
+
+ //if (NT_SUCCESS(status)) DbgPrint("%p: %p\r\n", _ReturnAddress(), *KeyHandle);
+
+ status = StopTailCallOptimization(status);
+
+ return status;
+}
+#endif
+
+
_FX NTSTATUS Key_NtCreateKeyImpl(
HANDLE *KeyHandle,
ACCESS_MASK DesiredAccess,
@@ -1119,6 +1172,17 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
BOOLEAN CopyPathCreated;
BOOLEAN TruePathExists;
PSECURITY_DESCRIPTOR *OverrideSecurityDescriptor;
+ ULONG TruePathFlags;
+ WCHAR* OriginalPath;
+ BOOLEAN TrueOpened;
+
+#ifdef WITH_DEBUG_
+ if (__sys_NtCreateKey_ == NULL)
+ {
+ __sys_NtCreateKey_ = __sys_NtCreateKey;
+ __sys_NtCreateKey = Key_MyCreateKey;
+ }
+#endif
//
// if this is a recursive invocation of NtCreateKey,
@@ -1146,6 +1210,8 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
CopyPathCreated = FALSE;
TruePathExists = FALSE;
+ OriginalPath = NULL;
+ TrueOpened = FALSE;
TlsData->key_NtCreateKey_lock = TRUE;
@@ -1225,6 +1291,8 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
}
}
+ if (NT_SUCCESS(status)) TrueOpened = TRUE;
+
__leave;
#undef KEY_READ_WOW64
@@ -1256,6 +1324,8 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
Wow64KeyReadAccess = Key_GetWow64Flag(TruePath, KEY_READ);
+ RtlInitUnicodeString(&objname, CopyPath);
+
//
// first we try to create or open CopyPath with whatever DesiredAccess
// the caller specified. if this succeeds, then CopyPath must exist
@@ -1263,8 +1333,7 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
// we also check that the parent of the key is not marked deleted.
//
- RtlInitUnicodeString(&objname, CopyPath);
-
+ if (!Key_Delete_v2)
if (Key_CheckDeletedParent(CopyPath)) {
//
@@ -1310,6 +1379,7 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
// requested copy key so that we can open it
//
+ if (!Dll_CompartmentMode) // NoDriverAssist
if (status == STATUS_ACCESS_DENIED && Secure_IsRestrictedToken(TRUE)) {
NTSTATUS status2 = SbieApi_SetLowLabelKey(CopyPath);
@@ -1350,9 +1420,12 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
if (NT_SUCCESS(status)) {
- BOOLEAN KeyDeleted = Key_CheckDeletedKey(*KeyHandle);
+ BOOLEAN KeyDeleted = FALSE;
- if (KeyDeleted) {
+ if (!Key_Delete_v2)
+ if (Key_CheckDeletedKey(*KeyHandle)) {
+
+ KeyDeleted = TRUE;
if (CreateOptions == tzuk) {
@@ -1417,6 +1490,28 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
__leave;
}
+ //
+ // Check true path relocation
+ //
+
+ TruePathFlags = 0;
+
+ if (Key_Delete_v2) {
+
+ WCHAR* OldTruePath = Key_ResolveTruePath(TruePath, &TruePathFlags);
+ if (OldTruePath) {
+ OriginalPath = TruePath;
+ TruePath = OldTruePath;
+ }
+
+ // if key marked as deleted dont even try opening true path
+ if (KEY_PATH_DELETED(TruePathFlags) && CreateOptions == tzuk) {
+ status = STATUS_OBJECT_NAME_NOT_FOUND;
+ __leave;
+ }
+ }
+
+
//
// if we're successful, or we got any of the three status codes
// that we don't handle, then stop here
@@ -1447,7 +1542,10 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
int depth = Key_CheckDepthForIsWritePath(TruePath);
if (depth == 0) {
- status = SbieApi_OpenKey(KeyHandle, TruePath);
+ if (Dll_CompartmentMode) { // NoDriverAssist
+ status = __sys_NtOpenKey(KeyHandle, Wow64KeyReadAccess, &objattrs);
+ } else
+ status = SbieApi_OpenKey(KeyHandle, TruePath);
if (NT_SUCCESS(status))
goto SkipReadOnlyCheck;
} else
@@ -1464,6 +1562,8 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
if (NT_SUCCESS(status)) {
+ TrueOpened = TRUE;
+
//
// if the TruePath key exists, and caller is asking for
// read-only (*) access to this key, then return the handle
@@ -1614,6 +1714,8 @@ SkipReadOnlyCheck:
status = __sys_NtOpenKey(
KeyHandle, DesiredAccess, ObjectAttributes);
+ if (NT_SUCCESS(status)) TrueOpened = TRUE; // is that right?
+
if (NT_SUCCESS(status) && Disposition)
*Disposition = REG_OPENED_EXISTING_KEY;
}
@@ -1627,6 +1729,19 @@ SkipReadOnlyCheck:
if (CopyPathCreated)
Key_DiscardMergeByPath(TruePath, TRUE);
+ //
+ // Relocation, if we opened the true key and its relocated set the path info
+ //
+
+ if (TrueOpened && OriginalPath) {
+
+ Handle_SetRelocationPath(*KeyHandle, OriginalPath);
+ }
+
+ //
+ // finish
+ //
+
Dll_PopTlsNameBuffer(TlsData);
TlsData->key_NtCreateKey_lock = FALSE;
@@ -1654,6 +1769,34 @@ _FX NTSTATUS Key_CreatePath(
USHORT savemaximumlength;
ULONG disp;
+ if (Key_Delete_v2) {
+
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ BOOLEAN ParentDeleted = FALSE;
+ WCHAR *TruePath;
+ WCHAR *CopyPath;
+
+ Dll_PushTlsNameBuffer(TlsData);
+
+ __try {
+
+ status = Key_GetName(NULL, objattrs->ObjectName, &TruePath, &CopyPath, NULL);
+
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ status = GetExceptionCode();
+ }
+
+ if (NT_SUCCESS(status)) {
+ ParentDeleted = KEY_PARENT_DELETED(Key_IsDeleted_v2(TruePath));
+ }
+
+ Dll_PopTlsNameBuffer(TlsData);
+
+ if(ParentDeleted)
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
//
// first we traverse backward along the path, removing the last
// path component each time, and trying to create the path that
@@ -1702,6 +1845,7 @@ _FX NTSTATUS Key_CreatePath(
if (NT_SUCCESS(status)) {
+ if (!Key_Delete_v2)
if (disp == REG_OPENED_EXISTING_KEY) {
if (Key_CheckDeletedKey(handle)) {
@@ -1746,6 +1890,7 @@ _FX NTSTATUS Key_CreatePath(
status = Key_CreatePath_Key(&handle, objattrs, &disp);
+ if (!Dll_CompartmentMode) // NoDriverAssist
if (status == STATUS_ACCESS_DENIED && Dll_RestrictedToken) {
//
@@ -2043,7 +2188,7 @@ _FX NTSTATUS Key_NtDeleteKeyTreeImpl(HANDLE KeyHandle, BOOLEAN DeleteTree)
// open the key. this will create a copy key, if necessary
//
- status = Key_NtOpenKeyImpl(&handle, GENERIC_WRITE | KEY_READ, &objattrs);
+ status = Key_NtOpenKeyImpl(&handle, GENERIC_WRITE | KEY_READ | DELETE, &objattrs);
if (! NT_SUCCESS(status))
__leave;
@@ -2182,17 +2327,51 @@ _FX NTSTATUS Key_MarkDeletedAndClose(HANDLE KeyHandle)
// mark key deleted by setting its last write time information
//
- kwti.LastWriteTime.HighPart = DELETE_MARK_HIGH;
- kwti.LastWriteTime.LowPart = DELETE_MARK_LOW;
- status = NtSetInformationKey(
- KeyHandle, KeyWriteTimeInformation,
- &kwti, sizeof(KEY_WRITE_TIME_INFORMATION));
+ if (Key_Delete_v2) {
- //
- // refresh all merges
- //
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
- Key_DiscardMergeByHandle(TlsData, KeyHandle, TRUE);
+ UNICODE_STRING objname;
+ WCHAR *TruePath;
+ WCHAR *CopyPath;
+
+ Dll_PushTlsNameBuffer(TlsData);
+
+ RtlInitUnicodeString(&objname, L"");
+
+ __try {
+
+ status = Key_GetName(KeyHandle, &objname, &TruePath, &CopyPath, NULL);
+
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ status = GetExceptionCode();
+ }
+
+ if (NT_SUCCESS(status)) {
+ Key_MarkDeletedEx_v2(TruePath, NULL);
+
+ Key_DiscardMergeByPath(TruePath, TRUE);
+ }
+
+ Dll_PopTlsNameBuffer(TlsData);
+
+ __sys_NtDeleteKey(KeyHandle);
+
+ }
+ else {
+
+ kwti.LastWriteTime.HighPart = DELETE_MARK_HIGH;
+ kwti.LastWriteTime.LowPart = DELETE_MARK_LOW;
+ status = NtSetInformationKey(
+ KeyHandle, KeyWriteTimeInformation,
+ &kwti, sizeof(KEY_WRITE_TIME_INFORMATION));
+
+ //
+ // refresh all merges
+ //
+
+ Key_DiscardMergeByHandle(TlsData, KeyHandle, TRUE);
+ }
//
// close key handle
@@ -2307,14 +2486,18 @@ _FX NTSTATUS Key_NtDeleteValueKey(
status = GetExceptionCode();
}
- Dll_PopTlsNameBuffer(TlsData);
-
if (NT_SUCCESS(status)) {
if (PATH_IS_OPEN(mp_flags)) {
status = __sys_NtDeleteValueKey(KeyHandle, ValueName);
+ } if (Key_Delete_v2){
+
+ Key_MarkDeletedEx_v2(TruePath, ValueName->Buffer);
+
+ __sys_NtDeleteValueKey(KeyHandle, ValueName);
+
} else {
//
@@ -2341,6 +2524,8 @@ _FX NTSTATUS Key_NtDeleteValueKey(
}
}
+ Dll_PopTlsNameBuffer(TlsData);
+
SetLastError(LastError);
return status;
}
@@ -2495,6 +2680,16 @@ _FX NTSTATUS Key_NtQueryKeyImpl(
__try {
+ //
+ // get the full paths for the true and copy keys
+ //
+
+ RtlInitUnicodeString(&objname, L"");
+
+ status = Key_GetName(KeyHandle, &objname, &TruePath, &CopyPath, NULL);
+ if (! NT_SUCCESS(status))
+ __leave;
+
//
// for KeyBasicInformation, KeyNodeInformation, KeyFlagsInformation,
// we let the system handle the call, then check for the delete mark.
@@ -2509,26 +2704,21 @@ _FX NTSTATUS Key_NtQueryKeyImpl(
KeyHandle, KeyInformationClass, KeyInformation,
Length, ResultLength);
- if (KeyInformationClass != KeyFlagsInformation &&
- (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
- IS_DELETE_MARK((LARGE_INTEGER *)KeyInformation))
+ if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW)
{
- status = STATUS_KEY_DELETED;
+ if (Key_Delete_v2) {
+ if (Key_IsDeleted_v2(TruePath))
+ status = STATUS_KEY_DELETED;
+ }
+ else if(KeyInformationClass != KeyFlagsInformation) {
+ if (IS_DELETE_MARK((LARGE_INTEGER*)KeyInformation))
+ status = STATUS_KEY_DELETED;
+ }
}
__leave;
}
- //
- // get the full paths for the true and copy keys
- //
-
- RtlInitUnicodeString(&objname, L"");
-
- status = Key_GetName(KeyHandle, &objname, &TruePath, &CopyPath, NULL);
- if (! NT_SUCCESS(status))
- __leave;
-
//
// for KeyNameInformation, we want to place TruePath in the
// output buffer, even if KeyHandle is a boxed key. this is
@@ -2601,10 +2791,16 @@ _FX NTSTATUS Key_NtQueryKeyImpl(
KeyHandle, KeyInformationClass, KeyInformation,
Length, ResultLength);
- if ((NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
- IS_DELETE_MARK((LARGE_INTEGER *)KeyInformation))
+ if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW)
{
- status = STATUS_KEY_DELETED;
+ if (Key_Delete_v2) {
+ if (Key_IsDeleted_v2(TruePath))
+ status = STATUS_KEY_DELETED;
+ }
+ else {
+ if (IS_DELETE_MARK((LARGE_INTEGER*)KeyInformation))
+ status = STATUS_KEY_DELETED;
+ }
}
}
@@ -2789,10 +2985,16 @@ _FX NTSTATUS Key_NtEnumerateKey(
KeyHandle, Index, KeyInformationClass, KeyInformation,
Length, ResultLength);
- if ((NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
- IS_DELETE_MARK((LARGE_INTEGER *)KeyInformation))
+ if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW)
{
- status = STATUS_KEY_DELETED;
+ if (Key_Delete_v2) {
+ if (Key_IsDeleted_v2(TruePath))
+ status = STATUS_KEY_DELETED;
+ }
+ else {
+ if (IS_DELETE_MARK((LARGE_INTEGER*)KeyInformation))
+ status = STATUS_KEY_DELETED;
+ }
}
}
@@ -3188,11 +3390,16 @@ _FX NTSTATUS Key_NtQueryValueKey(
KeyValueInformationClass, KeyValueInformation,
Length, ResultLength);
- if ((NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
- Key_CheckDeletedValue(
- KeyValueInformationClass, KeyValueInformation))
+ if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW)
{
- status = STATUS_OBJECT_NAME_NOT_FOUND;
+ if (Key_Delete_v2) {
+ if(Key_IsDeletedEx_v2(TruePath, ValueNameBuf, TRUE))
+ status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ else {
+ if (Key_CheckDeletedValue(KeyValueInformationClass, KeyValueInformation))
+ status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
}
}
@@ -3544,11 +3751,26 @@ _FX NTSTATUS Key_NtEnumerateValueKey(
KeyValueInformationClass, KeyValueInformation,
Length, ResultLength);
- if ((NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
- Key_CheckDeletedValue(
- KeyValueInformationClass, KeyValueInformation))
+ if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW)
{
- status = STATUS_OBJECT_NAME_NOT_FOUND;
+ if (Key_Delete_v2) {
+
+ WCHAR* ValueName;
+
+ if (KeyValueInformationClass == KeyValueBasicInformation)
+ ValueName = ((KEY_VALUE_BASIC_INFORMATION *)KeyValueInformation)->Name;
+ else if (KeyValueInformationClass == KeyValueFullInformation)
+ ValueName = ((KEY_VALUE_FULL_INFORMATION *)KeyValueInformation)->Name;
+ else
+ ValueName = 0;
+
+ if(ValueName && Key_IsDeletedEx_v2(TruePath, ValueName, TRUE))
+ status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ else {
+ if (Key_CheckDeletedValue(KeyValueInformationClass, KeyValueInformation))
+ status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
}
}
@@ -4068,8 +4290,153 @@ _FX HANDLE Key_GetTrueHandle(HANDLE KeyHandle, BOOLEAN *pIsOpenPath)
_FX NTSTATUS Key_NtRenameKey(
HANDLE KeyHandle, UNICODE_STRING *ReplacementName)
{
- SbieApi_Log(2205, L"NtRenameKey");
- return __sys_NtRenameKey(KeyHandle, ReplacementName);
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ if (!Key_Delete_v2) {
+ SbieApi_Log(2205, L"NtRenameKey");
+ return __sys_NtRenameKey(KeyHandle, ReplacementName);
+ }
+
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES objattrs;
+ UNICODE_STRING objname;
+ HANDLE handle;
+ WCHAR* TruePath;
+ WCHAR* CopyPath;
+ WCHAR* NewTruePath;
+
+ Dll_PushTlsNameBuffer(TlsData);
+
+ //
+ // get the full new name of the key to be renamed
+ //
+
+ __try {
+
+ status = Key_GetName(KeyHandle, NULL, &TruePath, &CopyPath, NULL);
+
+ WCHAR* TruePathSlash = wcsrchr(TruePath, L'\\');
+ if (!TruePathSlash) {
+ status = STATUS_INVALID_PARAMETER;
+ __leave;
+ }
+ ULONG len = (ULONG)(TruePathSlash - TruePath + 1);
+
+ NewTruePath = Dll_GetTlsNameBuffer(TlsData, MOVE_NAME_BUFFER,
+ len * sizeof(WCHAR) + ReplacementName->Length + sizeof(WCHAR));
+
+ wmemcpy(NewTruePath, TruePath, len);
+ wmemcpy(NewTruePath + len, ReplacementName->Buffer, ReplacementName->Length / sizeof(WCHAR));
+ NewTruePath[len + ReplacementName->Length / sizeof(WCHAR)] = L'\0';
+
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) {
+ status = GetExceptionCode();
+ }
+
+ //
+ // rename the key ensuring we wil have a boxed copy
+ //
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // check if the target key already exists in the true path
+ //
+
+ RtlInitUnicodeString(&objname, NewTruePath);
+ InitializeObjectAttributes(
+ &objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = __sys_NtOpenKey(&handle, KEY_READ, &objattrs);
+
+ if (NT_SUCCESS(status)) {
+
+ if(!Key_IsDeleted_v2(NewTruePath))
+ status = STATUS_OBJECT_NAME_COLLISION;
+
+ File_NtCloseImpl(handle);
+ }
+
+ //
+ // try renaming if it fails with access denided try again with a new handle
+ //
+
+ if (NT_SUCCESS(status))
+ status = __sys_NtRenameKey(KeyHandle, ReplacementName);
+
+ if (status == STATUS_ACCESS_DENIED) {
+
+ //
+ // if we get STATUS_ACCESS_DENIED, the caller may be using a
+ // TruePath handle that was opened with MAXIMUM_ALLOWED, but
+ // reduced to read-only access in our NtCreateKey
+ //
+
+ OBJECT_ATTRIBUTES objattrs;
+ UNICODE_STRING objname;
+ HANDLE handle;
+
+ RtlInitUnicodeString(&objname, L"");
+ InitializeObjectAttributes(
+ &objattrs, &objname, OBJ_CASE_INSENSITIVE, KeyHandle, NULL);
+
+ status = NtOpenKey(&handle, KEY_WRITE, &objattrs);
+
+ if (NT_SUCCESS(status)) {
+
+ status = __sys_NtRenameKey(handle, ReplacementName);
+
+ NtClose(handle);
+ }
+ }
+ }
+
+ //
+ // set the redirection information
+ //
+
+ if (NT_SUCCESS(status)) {
+
+ //*TruePathSlash = L'\0';
+ //Key_DiscardMergeByPath(TruePath, TRUE); // fix-me: act on Key_MergeCacheList
+ //*TruePathSlash = L'\\';
+
+ //
+ // check if the true path exists and if so mark path deleted
+ //
+
+ BOOLEAN TrueExists = FALSE;
+
+ RtlInitUnicodeString(&objname, TruePath);
+ InitializeObjectAttributes(
+ &objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = __sys_NtOpenKey(&handle, KEY_READ, &objattrs);
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // if the true key exists mark it deleted
+ //
+
+ TrueExists = TRUE;
+
+ File_NtCloseImpl(handle);
+ }
+
+ //
+ // setup/update the key relocation
+ //
+
+ Key_SetRelocation(TruePath, NewTruePath, TrueExists);
+
+ status = STATUS_SUCCESS;
+ }
+
+ Dll_PopTlsNameBuffer(TlsData);
+
+ return status;
}
@@ -4081,7 +4448,7 @@ _FX NTSTATUS Key_NtRenameKey(
_FX NTSTATUS Key_NtSaveKey(
HANDLE KeyHandle, HANDLE FileHandle)
{
- //SbieApi_Log(2205, L"NtSaveKey");
+ SbieApi_Log(2205, L"NtSaveKey");
return STATUS_SUCCESS;
}
@@ -4106,6 +4473,10 @@ _FX NTSTATUS Key_NtLoadKey(
FILE_LOAD_KEY_REQ *req;
status = __sys_NtLoadKey(TargetObjectAttributes, SourceObjectAttributes);
+
+ if (Dll_CompartmentMode) // NoDriverAssist
+ return status;
+
if (status != STATUS_PRIVILEGE_NOT_HELD)
return status;
diff --git a/Sandboxie/core/dll/key_del.c b/Sandboxie/core/dll/key_del.c
new file mode 100644
index 00000000..1f887753
--- /dev/null
+++ b/Sandboxie/core/dll/key_del.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2022 David Xanatos, xanasoft.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+//---------------------------------------------------------------------------
+// Key (Delete)
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#define KEY_PATH_FILE_NAME L"RegPaths.dat"
+
+// Keep in sync with the FILE_..._FLAG's in file_del.c
+//
+// path flages, saved to file
+#define KEY_DELETED_FLAG 0x0001
+#define KEY_RELOCATION_FLAG 0x0002
+
+// internal volatile status flags
+#define KEY_PATH_DELETED_FLAG 0x00010000
+#define KEY_PATH_RELOCATED_FLAG 0x00020000
+#define KEY_CHILDREN_DELETED_FLAG 0x00040000
+
+#define KEY_DELETED_MASK (KEY_DELETED_FLAG | KEY_PATH_DELETED_FLAG)
+#define KEY_RELOCATED_MASK (KEY_RELOCATION_FLAG | KEY_PATH_RELOCATED_FLAG)
+
+#define KEY_IS_DELETED(x) ((x & KEY_DELETED_FLAG) != 0)
+#define KEY_PATH_DELETED(x) ((x & KEY_DELETED_MASK) != 0)
+#define KEY_PARENT_DELETED(x) ((x & KEY_PATH_DELETED_FLAG) != 0)
+#define KEY_PATH_RELOCATED(x) ((x & KEY_RELOCATED_MASK) != 0)
+
+
+//---------------------------------------------------------------------------
+// Variables
+//---------------------------------------------------------------------------
+
+
+static LIST Key_PathRoot;
+static CRITICAL_SECTION *Key_PathRoot_CritSec = NULL;
+
+static HANDLE Key_BoxRootWatcher = NULL;
+static volatile ULONGLONG Key_PathsVersion = 0; // count reloads
+
+
+//---------------------------------------------------------------------------
+// Functions
+//---------------------------------------------------------------------------
+
+static ULONG Key_GetPathFlags(const WCHAR* Path, WCHAR** pRelocation);
+static BOOLEAN Key_SavePathTree();
+static BOOLEAN Key_LoadPathTree();
+static VOID Key_RefreshPathTree();
+BOOLEAN Key_InitDelete_v2();
+static NTSTATUS Key_MarkDeletedEx_v2(const WCHAR* TruePath, const WCHAR* ValueName);
+static ULONG Key_IsDeleted_v2(const WCHAR* TruePath);
+static ULONG Key_IsDeletedEx_v2(const WCHAR* TruePath, const WCHAR* ValueName, BOOLEAN IsValue);
+
+//
+// we re use the _internal functions of the file implementation as thay all are generic enough
+//
+
+VOID File_ClearPathBranche_internal(LIST* parent);
+VOID File_SavePathTree_internal(LIST* Root, const WCHAR* name);
+VOID File_LoadPathTree_internal(LIST* Root, const WCHAR* name);
+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);
+VOID File_MarkDeleted_internal(LIST* Root, const WCHAR* Path);
+VOID File_SetRelocation_internal(LIST* Root, const WCHAR* OldTruePath, const WCHAR* NewTruePath, BOOLEAN TrueExists);
+
+
+
+//---------------------------------------------------------------------------
+// Key_GetPathFlags
+//---------------------------------------------------------------------------
+
+
+_FX ULONG Key_GetPathFlags(const WCHAR* Path, WCHAR** pRelocation)
+{
+ ULONG Flags;
+
+ Key_RefreshPathTree();
+
+ EnterCriticalSection(Key_PathRoot_CritSec);
+
+ Flags = File_GetPathFlags_internal(&Key_PathRoot, Path, pRelocation, TRUE);
+
+ LeaveCriticalSection(Key_PathRoot_CritSec);
+
+ return Flags;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_SavePathTree
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN Key_SavePathTree()
+{
+ EnterCriticalSection(Key_PathRoot_CritSec);
+
+ File_SavePathTree_internal(&Key_PathRoot, KEY_PATH_FILE_NAME);
+
+ LeaveCriticalSection(Key_PathRoot_CritSec);
+
+ Key_PathsVersion++;
+
+ return TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_LoadPathTree
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN Key_LoadPathTree()
+{
+ EnterCriticalSection(Key_PathRoot_CritSec);
+
+ File_LoadPathTree_internal(&Key_PathRoot, KEY_PATH_FILE_NAME);
+
+ LeaveCriticalSection(Key_PathRoot_CritSec);
+
+ Key_PathsVersion++;
+
+ return TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_RefreshPathTree
+//---------------------------------------------------------------------------
+
+
+_FX VOID Key_RefreshPathTree()
+{
+ if (!Key_BoxRootWatcher)
+ return;
+
+ if (WaitForSingleObject(Key_BoxRootWatcher, 0) == WAIT_OBJECT_0) {
+
+ //
+ // somethign changed, reload the path tree
+ //
+
+ Key_LoadPathTree();
+ }
+
+ FindNextChangeNotification(Key_BoxRootWatcher); // rearm the watcher
+}
+
+
+//---------------------------------------------------------------------------
+// Key_InitDelete_v2
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN Key_InitDelete_v2()
+{
+ List_Init(&Key_PathRoot);
+
+ Key_PathRoot_CritSec = Dll_Alloc(sizeof(CRITICAL_SECTION));
+ InitializeCriticalSectionAndSpinCount(Key_PathRoot_CritSec, 1000);
+
+ Key_LoadPathTree();
+
+//#ifdef WITH_DEBUG
+// Key_SavePathTree();
+//#endif
+
+ WCHAR BoxFilePath[MAX_PATH] = { 0 };
+ wcscpy(BoxFilePath, Dll_BoxFilePath);
+ SbieDll_TranslateNtToDosPath(BoxFilePath);
+
+ Key_BoxRootWatcher = FindFirstChangeNotification(BoxFilePath, FALSE, FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE);
+
+ return TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_MarkDeletedEx_v2
+//---------------------------------------------------------------------------
+
+
+_FX NTSTATUS Key_MarkDeletedEx_v2(const WCHAR* TruePath, const WCHAR* ValueName)
+{
+ //
+ // add a key/value or directory to the deleted list
+ //
+
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ WCHAR* FullPath = Dll_GetTlsNameBuffer(TlsData, TMPL_NAME_BUFFER,
+ (wcslen(TruePath) + (ValueName ? wcslen(ValueName) : 0) + 16) * sizeof(WCHAR)); // template buffer is not used for reg reputpose it here
+
+ wcscpy(FullPath, TruePath);
+ if (ValueName) {
+ wcscat(FullPath, L"\\$");
+ wcscat(FullPath, ValueName);
+ }
+
+ EnterCriticalSection(Key_PathRoot_CritSec);
+
+ File_MarkDeleted_internal(&Key_PathRoot, FullPath);
+
+ LeaveCriticalSection(Key_PathRoot_CritSec);
+
+ Key_SavePathTree();
+
+ return STATUS_SUCCESS;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_IsDeleted_v2
+//---------------------------------------------------------------------------
+
+
+_FX ULONG Key_IsDeleted_v2(const WCHAR* TruePath)
+{
+ //
+ // check if the key/value or one of its parent directories is listed as deleted
+ //
+
+ ULONG Flags = Key_GetPathFlags(TruePath, NULL);
+
+ return (Flags & KEY_DELETED_MASK);
+}
+
+
+//---------------------------------------------------------------------------
+// Key_IsDeletedEx_v2
+//---------------------------------------------------------------------------
+
+
+_FX ULONG Key_IsDeletedEx_v2(const WCHAR* TruePath, const WCHAR* ValueName, BOOLEAN IsValue)
+{
+ //
+ // check if the key/value or one of its parent directories is listed as deleted
+ //
+
+ THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
+
+ WCHAR* FullPath = Dll_GetTlsNameBuffer(TlsData, TMPL_NAME_BUFFER,
+ (wcslen(TruePath) + (ValueName ? wcslen(ValueName) : 0) + 16) * sizeof(WCHAR)); // template buffer is not used for reg reputpose it here
+
+ wcscpy(FullPath, TruePath);
+ if (ValueName) {
+ wcscat(FullPath, IsValue ? L"\\$" : L"\\");
+ wcscat(FullPath, ValueName);
+ }
+
+ return Key_IsDeleted_v2(FullPath);
+}
+
+
+//---------------------------------------------------------------------------
+// Key_HasDeleted_v2
+//---------------------------------------------------------------------------
+
+
+_FX BOOLEAN Key_HasDeleted_v2(const WCHAR* TruePath)
+{
+ //
+ // Check if this folder has deleted children
+ //
+
+ ULONG Flags = Key_GetPathFlags(TruePath, NULL);
+
+ return (Flags & KEY_CHILDREN_DELETED_FLAG) != 0;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_SetRelocation
+//---------------------------------------------------------------------------
+
+
+_FX NTSTATUS Key_SetRelocation(const WCHAR *OldTruePath, const WCHAR *NewTruePath, BOOLEAN TrueExists)
+{
+ //
+ // List a mapping for the new location
+ //
+
+ EnterCriticalSection(Key_PathRoot_CritSec);
+
+ File_SetRelocation_internal(&Key_PathRoot, OldTruePath, NewTruePath, TrueExists);
+
+ LeaveCriticalSection(Key_PathRoot_CritSec);
+
+ Key_SavePathTree();
+
+ return STATUS_SUCCESS;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_GetRelocation
+//---------------------------------------------------------------------------
+
+
+_FX WCHAR* Key_GetRelocation(const WCHAR *TruePath)
+{
+ //
+ // Get redirection location, only if its the actual path and not a parent
+ //
+
+ WCHAR* OldTruePath = NULL;
+ ULONG Flags = Key_GetPathFlags(TruePath, &OldTruePath);
+ if (KEY_PATH_RELOCATED(Flags))
+ return OldTruePath;
+
+ return NULL;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_ResolveTruePath
+//---------------------------------------------------------------------------
+
+
+_FX WCHAR* Key_ResolveTruePath(const WCHAR *TruePath, ULONG* PathFlags)
+{
+ //
+ // Resolve the true path, taking into account redirection locations of parent folder
+ //
+
+ WCHAR* OldTruePath = NULL;
+ ULONG Flags = Key_GetPathFlags(TruePath, &OldTruePath);
+ if (PathFlags) *PathFlags = Flags;
+
+ return OldTruePath;
+}
+
diff --git a/Sandboxie/core/dll/key_merge.c b/Sandboxie/core/dll/key_merge.c
index a4488fed..f8bf90c8 100644
--- a/Sandboxie/core/dll/key_merge.c
+++ b/Sandboxie/core/dll/key_merge.c
@@ -1,5 +1,6 @@
/*
* Copyright 2004-2020 Sandboxie Holdings, LLC
+ * Copyright 2021-2022 David Xanatos, xanasoft.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,6 +36,7 @@ typedef struct _KEY_MERGE {
BOOLEAN subkeys_merged;
LARGE_INTEGER last_write_time;
+ ULONGLONG last_paths_version;
LIST subkeys;
ULONG last_index;
@@ -200,7 +202,7 @@ _FX NTSTATUS Key_Merge(
// if we got here, we need to discard the stale entry
//
- File_UnRegisterCloseHandler(merge->handle, Key_NtClose);
+ Handle_UnRegisterCloseHandler(merge->handle, Key_NtClose);
List_Remove(&Key_Handles, merge);
Key_MergeFree(merge, TRUE);
@@ -226,7 +228,7 @@ _FX NTSTATUS Key_Merge(
memcpy(merge->name, TruePath, TruePath_len + sizeof(WCHAR));
List_Insert_Before(&Key_Handles, NULL, merge);
- File_RegisterCloseHandler(merge->handle, Key_NtClose);
+ Handle_RegisterCloseHandler(merge->handle, Key_NtClose);
}
//
@@ -234,6 +236,7 @@ _FX NTSTATUS Key_Merge(
// or CopyPath exist, but not both, so return special status
//
+ if(!Key_Delete_v2 || !Key_HasDeleted_v2(TruePath))
if (merge->cant_merge) {
LeaveCriticalSection(&Key_Handles_CritSec);
@@ -316,6 +319,7 @@ _FX NTSTATUS Key_OpenForMerge(
ULONG len;
HANDLE TrueHandle;
ULONG mp_flags;
+ const WCHAR* OriginalPath = NULL;
*out_TrueMerge = NULL;
*out_CopyHandle = NULL;
@@ -362,6 +366,7 @@ _FX NTSTATUS Key_OpenForMerge(
&info, sizeof(KEY_BASIC_INFORMATION), &len);
if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) {
+ // if (!Key_Delete_v2 &&
if (IS_DELETE_MARK(&info.LastWriteTime))
status = STATUS_KEY_DELETED;
else
@@ -379,7 +384,10 @@ _FX NTSTATUS Key_OpenForMerge(
// if we couldn't find a copy key, indicate there is nothing to merge
//
- status = STATUS_BAD_INITIAL_PC;
+ if (Key_Delete_v2 && Key_HasDeleted_v2(TruePath))
+ status = STATUS_SUCCESS;
+ else
+ status = STATUS_BAD_INITIAL_PC;
}
if (! NT_SUCCESS(status)) {
@@ -387,6 +395,18 @@ _FX NTSTATUS Key_OpenForMerge(
return status;
}
+ //
+ // get the redirection location for this key if there is one
+ //
+
+ if (Key_Delete_v2) {
+ WCHAR* OldTruePath = Key_GetRelocation(TruePath);
+ if (OldTruePath) {
+ OriginalPath = TruePath;
+ TruePath = OldTruePath;
+ }
+ }
+
//
// open TruePath for KEY_READ access. we use __sys_NtOpenKey
// because we really want the TruePath key, even if there is
@@ -415,7 +435,7 @@ _FX NTSTATUS Key_OpenForMerge(
if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) {
status = Key_MergeCache(
- TrueHandle, &info.LastWriteTime, TruePath, out_TrueMerge);
+ TrueHandle, &info.LastWriteTime, OriginalPath ? OriginalPath : TruePath, out_TrueMerge);
}
File_NtCloseImpl(TrueHandle);
@@ -623,7 +643,7 @@ _FX NTSTATUS Key_MergeCache(
if (merge) {
- if (LastWriteTime->QuadPart == merge->last_write_time.QuadPart) {
+ if (LastWriteTime->QuadPart == merge->last_write_time.QuadPart && Key_PathsVersion == merge->last_paths_version) {
*out_TrueMerge = merge;
return STATUS_SUCCESS;
}
@@ -646,6 +666,7 @@ _FX NTSTATUS Key_MergeCache(
}
merge->last_write_time.QuadPart = LastWriteTime->QuadPart;
+ merge->last_paths_version = Key_PathsVersion;
//
// build the subkeys and values in the true merge
@@ -730,6 +751,12 @@ _FX NTSTATUS Key_MergeCacheSubkeys(KEY_MERGE *merge, HANDLE TrueHandle)
info->ClassOffset != -1 ||
info->ClassLength);
+ if (Key_Delete_v2 && Key_IsDeletedEx_v2(merge->name, subkey->name, FALSE)) {
+ Dll_Free(subkey);
+ ++index;
+ continue;
+ }
+
//
// find where to insert it. if the new key is already larger than
// our last key in the sorted list, instead directly at the end
@@ -828,6 +855,12 @@ _FX NTSTATUS Key_MergeCacheValues(KEY_MERGE *merge, HANDLE TrueHandle)
memcpy(value->data_ptr,
(UCHAR *)info + info->DataOffset, info->DataLength);
+ if (Key_Delete_v2 && Key_IsDeletedEx_v2(merge->name, value->name, TRUE)) {
+ Dll_Free(value);
+ ++index;
+ continue;
+ }
+
//
// find where to insert it
//
@@ -864,7 +897,7 @@ _FX NTSTATUS Key_MergeSubkeys(
KEY_NODE_INFORMATION *info;
ULONG index;
KEY_MERGE_SUBKEY *subkey, *subkey2;
- BOOLEAN subkey_deleted;
+ BOOLEAN subkey_deleted = FALSE;
//
// get the latest of the two LastWriteTime fields
@@ -882,6 +915,7 @@ _FX NTSTATUS Key_MergeSubkeys(
}
merge->last_write_time.QuadPart = info->LastWriteTime.QuadPart;
+ merge->last_paths_version = Key_PathsVersion;
if (! TrueMerge)
goto TrueHandleFinish;
@@ -962,6 +996,7 @@ TrueHandleFinish:
info->ClassOffset != -1 ||
info->ClassLength);
+ if (!Key_Delete_v2)
if (IS_DELETE_MARK(&info->LastWriteTime))
subkey_deleted = TRUE;
else
@@ -988,7 +1023,8 @@ TrueHandleFinish:
if (subkey->TitleOrClass)
subkey2->TitleOrClass = subkey->TitleOrClass;
}
- subkey_deleted = TRUE;
+ Dll_Free(subkey);
+ subkey = NULL;
break;
}
@@ -1033,7 +1069,7 @@ _FX NTSTATUS Key_MergeValues(
KEY_VALUE_FULL_INFORMATION *info;
ULONG index;
KEY_MERGE_VALUE *value, *value2;
- BOOLEAN value_deleted;
+ BOOLEAN value_deleted = FALSE;
info_len = 128; // at least sizeof(KEY_VALUE_FULL_INFORMATION)
info = Dll_Alloc(info_len);
@@ -1125,6 +1161,7 @@ TrueHandleFinish:
memcpy(value->data_ptr,
(UCHAR *)info + info->DataOffset, value->data_len);
+ if (!Key_Delete_v2)
if (info->Type == tzuk)
value_deleted = TRUE;
else
@@ -1379,7 +1416,7 @@ _FX void Key_DiscardMergeByPath(const WCHAR *TruePath, BOOLEAN Recurse)
}
}
- File_UnRegisterCloseHandler(merge->handle, Key_NtClose);
+ Handle_UnRegisterCloseHandler(merge->handle, Key_NtClose);
List_Remove(&Key_Handles, merge);
Key_MergeFree(merge, TRUE);
}
diff --git a/Sandboxie/core/dll/proc.c b/Sandboxie/core/dll/proc.c
index 9bc5eef5..ac4b93da 100644
--- a/Sandboxie/core/dll/proc.c
+++ b/Sandboxie/core/dll/proc.c
@@ -1323,7 +1323,7 @@ _FX BOOL Proc_AlternateCreateProcess(
void *lpCurrentDirectory, LPPROCESS_INFORMATION lpProcessInformation,
BOOL *ReturnValue)
{
- if (SbieApi_QueryConfBool(NULL, L"BlockSoftwareUpdaters", FALSE))
+ //if (SbieApi_QueryConfBool(NULL, L"BlockSoftwareUpdaters", TRUE))
if (Proc_IsSoftwareUpdateW(lpApplicationName ? lpApplicationName : lpCommandLine)) {
SetLastError(ERROR_ACCESS_DENIED);
diff --git a/Sandboxie/core/dll/scm_msi.c b/Sandboxie/core/dll/scm_msi.c
index e8abab88..b8109afe 100644
--- a/Sandboxie/core/dll/scm_msi.c
+++ b/Sandboxie/core/dll/scm_msi.c
@@ -16,10 +16,13 @@
* along with this program. If not, see .
*/
+#include "handle.h"
+
//---------------------------------------------------------------------------
// Service Control Manager
//---------------------------------------------------------------------------
+
//#define ErrorMessageBox(txt)
//
//#define HOOK_WIN32(func) { \
@@ -237,7 +240,7 @@ _FX BOOL Scm_OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE
if (NT_SUCCESS(status) && ProcessHandle == GetCurrentProcess()) {
- File_RegisterCloseHandler(*phTokenOut, Scm_TokenCloseHandler);
+ Handle_RegisterCloseHandler(*phTokenOut, Scm_TokenCloseHandler);
TlsData->scm_last_own_token = *phTokenOut;
}
@@ -258,7 +261,7 @@ _FX BOOL Scm_OpenThreadToken(HANDLE ThreadHandle, DWORD DesiredAccess, BOOL Open
if (NT_SUCCESS(status) && ThreadHandle == GetCurrentThread()) {
- File_RegisterCloseHandler(*phTokenOut, Scm_TokenCloseHandler);
+ Handle_RegisterCloseHandler(*phTokenOut, Scm_TokenCloseHandler);
TlsData->scm_last_own_token = *phTokenOut;
}
diff --git a/Sandboxie/core/dll/secure.c b/Sandboxie/core/dll/secure.c
index da6a7ea4..9a5519bd 100644
--- a/Sandboxie/core/dll/secure.c
+++ b/Sandboxie/core/dll/secure.c
@@ -722,8 +722,17 @@ _FX NTSTATUS Secure_NtDuplicateObject(
if (SourceProcessHandle == NtCurrentProcess()) {
- if (TargetProcessHandle == NtCurrentProcess() && TargetHandle)
- File_DuplicateRecover(SourceHandle, *TargetHandle);
+ if (TargetProcessHandle == NtCurrentProcess() && TargetHandle) {
+
+ //
+ // this also duplicates the "recoverability"
+ // of the old handle to the new handle. needed in particular for
+ // SHFileOperation to recover correctly on Windows Vista
+ //
+
+ if(SourceHandle && *TargetHandle)
+ Handle_SetupDuplicate(SourceHandle, *TargetHandle);
+ }
if (SourceHandle)
Key_NtClose(SourceHandle);
diff --git a/Sandboxie/core/dll/sysinfo.c b/Sandboxie/core/dll/sysinfo.c
index b7a70746..5b4babe8 100644
--- a/Sandboxie/core/dll/sysinfo.c
+++ b/Sandboxie/core/dll/sysinfo.c
@@ -422,14 +422,26 @@ _FX NTSTATUS SysInfo_GetJobName(OBJECT_ATTRIBUTES* ObjectAttributes, WCHAR** Out
*OutCopyPath = name;
- wmemcpy(name, Dll_BoxIpcPath, Dll_BoxIpcPathLen);
- name += Dll_BoxIpcPathLen;
+ //if (Dll_AlernateIpcNaming)
+ //{
+ // wmemcpy(name, objname_buf, objname_len);
+ // name += objname_len;
+ //
+ // wmemcpy(name, Dll_BoxIpcPath, Dll_BoxIpcPathLen);
+ // name += Dll_BoxIpcPathLen;
+ //}
+ //else
+ {
+ wmemcpy(name, Dll_BoxIpcPath, Dll_BoxIpcPathLen);
+ name += Dll_BoxIpcPathLen;
- *name = L'\\';
- name++;
+ *name = L'\\';
+ name++;
+
+ wmemcpy(name, objname_buf, objname_len);
+ name += objname_len;
+ }
- wmemcpy(name, objname_buf, objname_len);
- name += objname_len;
*name = L'\0';
return STATUS_SUCCESS;
diff --git a/SandboxiePlus/QSbieAPI/Sandboxie/SandBox.cpp b/SandboxiePlus/QSbieAPI/Sandboxie/SandBox.cpp
index 7d9d87db..31b47bd2 100644
--- a/SandboxiePlus/QSbieAPI/Sandboxie/SandBox.cpp
+++ b/SandboxiePlus/QSbieAPI/Sandboxie/SandBox.cpp
@@ -323,6 +323,8 @@ struct SBoxDataFile
QList CSandBox__BoxDataFiles = QList()
<< SBoxDataFile("RegHive", true, false)
+ << SBoxDataFile("RegPaths.dat", false, false)
+ << SBoxDataFile("FilePaths.dat", false, true)
;
bool CSandBox::IsInitialized() const
diff --git a/SandboxiePlus/version.h b/SandboxiePlus/version.h
index 24fbad8d..8eabf5ee 100644
--- a/SandboxiePlus/version.h
+++ b/SandboxiePlus/version.h
@@ -1,8 +1,8 @@
#pragma once
#define VERSION_MJR 1
-#define VERSION_MIN 0
-#define VERSION_REV 10
+#define VERSION_MIN 1
+#define VERSION_REV 0
#define VERSION_UPD 0
#ifndef STR