commit
8babe4eb14
20
CHANGELOG.md
20
CHANGELOG.md
|
@ -6,7 +6,25 @@ 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 box size info [#1780](https://github.com/sandboxie-plus/Sandboxie/issues/1780)
|
||||
|
||||
### 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
|
||||
- reworked the TlsNameBuffer mechanism to be more versatile and less error prone
|
||||
- significantly reduced the CPU usage of sandman.exe
|
||||
|
||||
### Fixed
|
||||
- fixed folder rename issues (this requires UseFileDeleteV2=y) [#71](https://github.com/sandboxie-plus/Sandboxie/issues/71)
|
||||
- fixed issue with process access [#1603](https://github.com/sandboxie-plus/Sandboxie/issues/1603)
|
||||
- fixed translation issue [#1864](https://github.com/sandboxie-plus/Sandboxie/issues/1864)
|
||||
- fixed ui issue with box selection window [#1867](https://github.com/sandboxie-plus/Sandboxie/issues/1867)
|
||||
- fixed ui issue when switching language [#1871](https://github.com/sandboxie-plus/Sandboxie/issues/1871)
|
||||
|
||||
|
||||
|
||||
|
@ -92,7 +110,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||
|
||||
### Fixed
|
||||
- fixed pipe impersonation in compartment mode
|
||||
- fixed issue with box clean-up which was introduced in a recent build
|
||||
- fixed issue with box clean-up introduced in a recent build
|
||||
- fixed missing trace log clean-up command [#1773](https://github.com/sandboxie-plus/Sandboxie/issues/1773)
|
||||
- fixed inability to unpin programs that have been pinned to the run menu [#1694](https://github.com/sandboxie-plus/Sandboxie/issues/1694)
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
#ifndef _MY_VERSION_H
|
||||
#define _MY_VERSION_H
|
||||
|
||||
#define MY_VERSION_BINARY 5,55,22
|
||||
#define MY_VERSION_STRING "5.55.22"
|
||||
#define MY_VERSION_COMPAT "5.55.0" // this refers to the driver ABI compatibility
|
||||
#define MY_VERSION_BINARY 5,56,0
|
||||
#define MY_VERSION_STRING "5.56.0"
|
||||
#define MY_VERSION_COMPAT "5.56.0" // this refers to the driver ABI compatibility
|
||||
|
||||
// These #defines are used by either Resource Compiler or NSIS installer
|
||||
#define SBIE_INSTALLER_PATH "..\\Bin\\"
|
||||
|
@ -32,8 +32,8 @@
|
|||
|
||||
#define MY_PRODUCT_NAME_STRING "Sandboxie"
|
||||
#define MY_COMPANY_NAME_STRING "Sandboxie-Plus.com"
|
||||
#define MY_COPYRIGHT_STRING "Copyright © 2020-2022 by David Xanatos (xanasoft.com)"
|
||||
#define MY_COPYRIGHT_STRING_OLD "Copyright © 2004-2020 by Sandboxie Holdings, LLC"
|
||||
#define MY_COPYRIGHT_STRING "Copyright © 2020-2022 by David Xanatos (xanasoft.com)"
|
||||
#define MY_COPYRIGHT_STRING_OLD "Copyright © 2004-2020 by Sandboxie Holdings, LLC"
|
||||
|
||||
#define SANDBOXIE L"Sandboxie"
|
||||
#define SBIE L"SBIE"
|
||||
|
|
|
@ -545,6 +545,9 @@ BOOLEAN NetFw_ParseRule(NETFW_RULE* rule, const WCHAR* found_value)
|
|||
|
||||
static int isdigit_(int c) { return (c >= '0' && c <= '9'); }
|
||||
static int isxdigit_(int c) { return (isdigit_(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')); }
|
||||
#undef isascii
|
||||
static int isascii(int iChar) { return((iChar <= 127) && (iChar >= 0)); }
|
||||
static int isalnum_(int c) { return (isdigit_(c) || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// from BSD sources: http://code.google.com/p/plan9front/source/browse/sys/src/ape/lib/bsd/?r=320990f52487ae84e28961517a4fa0d02d473bac
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
<OmitFramePointers />
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<PreprocessorDefinitions>WITH_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ntdll.lib;uuid.lib;kernel32.lib</AdditionalDependencies>
|
||||
|
@ -117,6 +118,7 @@
|
|||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<PreprocessorDefinitions>WITH_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ntdll.lib;uuid.lib;kernel32.lib</AdditionalDependencies>
|
||||
|
@ -243,6 +245,12 @@
|
|||
<ClCompile Include="dump.c" />
|
||||
<ClCompile Include="event.c" />
|
||||
<ClCompile Include="file.c" />
|
||||
<ClCompile Include="file_del.c">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="file_dir.c">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">true</ExcludedFromBuild>
|
||||
|
@ -279,6 +287,18 @@
|
|||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="file_recovery.c">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="file_snapshots.c">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gdi.c" />
|
||||
<ClCompile Include="gui.c" />
|
||||
<ClCompile Include="guiclass.c" />
|
||||
|
@ -291,6 +311,7 @@
|
|||
<ClCompile Include="guimsg.c" />
|
||||
<ClCompile Include="guiprop.c" />
|
||||
<ClCompile Include="guititle.c" />
|
||||
<ClCompile Include="handle.c" />
|
||||
<ClCompile Include="hook_inst.c" />
|
||||
<ClCompile Include="hook_tramp.c" />
|
||||
<ClCompile Include="includes.c" />
|
||||
|
@ -305,6 +326,12 @@
|
|||
<ClCompile Include="ipstore_enum.cpp" />
|
||||
<ClCompile Include="ipstore_impl.cpp" />
|
||||
<ClCompile Include="key.c" />
|
||||
<ClCompile Include="key_del.c">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="key_merge.c">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">true</ExcludedFromBuild>
|
||||
|
@ -427,6 +454,7 @@
|
|||
<ClInclude Include="dump.h" />
|
||||
<ClInclude Include="guidlg.h" />
|
||||
<ClInclude Include="gui_p.h" />
|
||||
<ClInclude Include="handle.h" />
|
||||
<ClInclude Include="hook.h" />
|
||||
<ClInclude Include="ipstore_enum.h" />
|
||||
<ClInclude Include="ipstore_impl.h" />
|
||||
|
|
|
@ -6,11 +6,9 @@
|
|||
<ClCompile Include="custom.c" />
|
||||
<ClCompile Include="dllmem.c" />
|
||||
<ClCompile Include="dllpath.c" />
|
||||
<ClCompile Include="event.c" />
|
||||
<ClCompile Include="includes.c" />
|
||||
<ClCompile Include="lsa.c" />
|
||||
<ClCompile Include="mscoree.c" />
|
||||
<ClCompile Include="obj.c" />
|
||||
<ClCompile Include="pdh.c" />
|
||||
<ClCompile Include="proc.c" />
|
||||
<ClCompile Include="secure.c" />
|
||||
|
@ -218,6 +216,25 @@
|
|||
<ClCompile Include="dump.c">
|
||||
<Filter>debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="file_del.c">
|
||||
<Filter>file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="key_del.c">
|
||||
<Filter>key</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="obj.c">
|
||||
<Filter>obj</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="handle.c">
|
||||
<Filter>obj</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="event.c" />
|
||||
<ClCompile Include="file_recovery.c">
|
||||
<Filter>file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="file_snapshots.c">
|
||||
<Filter>file</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="advapi.h" />
|
||||
|
@ -255,9 +272,6 @@
|
|||
<ClInclude Include="sbiedll.h">
|
||||
<Filter>api</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="obj.h">
|
||||
<Filter>com</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\common\stream.h">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
|
@ -312,6 +326,12 @@
|
|||
<ClInclude Include="dump.h">
|
||||
<Filter>debug</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="obj.h">
|
||||
<Filter>obj</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="handle.h">
|
||||
<Filter>obj</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="resource.rc" />
|
||||
|
@ -373,6 +393,9 @@
|
|||
<Filter Include="debug">
|
||||
<UniqueIdentifier>{db0f9820-8908-4325-96f9-69c82fa9e268}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="obj">
|
||||
<UniqueIdentifier>{05955a21-494a-4624-854e-d7c9b1e33401}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="pstore.idl">
|
||||
|
|
|
@ -132,6 +132,20 @@ _FX UCHAR GetSetCustomLevel(UCHAR SetLevel)
|
|||
|
||||
if (! SetLevel) {
|
||||
|
||||
//
|
||||
// if UseRegDeleteV2 is set, check if RegPaths.dat was loaded
|
||||
// if not it means the box was previusly a V1 box,
|
||||
// hence return 0 and re run customization
|
||||
//
|
||||
// note: DeleteShellAssocKeys deletes the sandboxie shell integration keys
|
||||
// so the existence of a RegPaths.dat in a customized box is a reliable indicator
|
||||
//
|
||||
|
||||
extern BOOLEAN Key_Delete_v2;
|
||||
extern BOOLEAN Key_RegPaths_Loaded;
|
||||
if (Key_Delete_v2 && !Key_RegPaths_Loaded)
|
||||
return 0;
|
||||
|
||||
//
|
||||
// open the AutoExec key, also used to indicate if this sandbox
|
||||
// has already been customized
|
||||
|
|
|
@ -48,8 +48,9 @@ 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 NAME_BUFFER_DEPTH 24
|
||||
#define MISC_NAME_BUFFER 3 // 4, 5, 6, 7
|
||||
#define NAME_BUFFER_COUNT 8
|
||||
#define NAME_BUFFER_DEPTH 16 // 12
|
||||
|
||||
|
||||
#ifdef _WIN64
|
||||
|
@ -152,6 +153,7 @@ typedef struct _MY_LDR_WORKER_QUEUE_STUFF {
|
|||
}MY_LDR_WORKER_QUEUE_STUFF;
|
||||
#endif
|
||||
*/
|
||||
|
||||
typedef struct _THREAD_DATA {
|
||||
|
||||
//
|
||||
|
@ -160,7 +162,8 @@ typedef struct _THREAD_DATA {
|
|||
|
||||
WCHAR *name_buffer[NAME_BUFFER_COUNT][NAME_BUFFER_DEPTH];
|
||||
ULONG name_buffer_len[NAME_BUFFER_COUNT][NAME_BUFFER_DEPTH];
|
||||
int depth;
|
||||
int name_buffer_count[NAME_BUFFER_DEPTH];
|
||||
int name_buffer_depth;
|
||||
|
||||
//
|
||||
// locks
|
||||
|
@ -280,6 +283,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;
|
||||
|
||||
|
@ -455,7 +459,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);
|
||||
|
||||
|
@ -488,9 +492,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)
|
||||
|
@ -623,12 +625,18 @@ BOOLEAN Win32_Init(HMODULE hmodule);
|
|||
// Functions (init for DllMain)
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
BOOLEAN File_InitHandles(void);
|
||||
BOOLEAN Handle_Init(void);
|
||||
|
||||
BOOLEAN Key_Init(void);
|
||||
|
||||
extern BOOLEAN Key_Delete_v2;
|
||||
BOOLEAN Key_InitDelete_v2();
|
||||
|
||||
BOOLEAN File_Init(void);
|
||||
|
||||
extern BOOLEAN File_Delete_v2;
|
||||
BOOLEAN File_InitDelete_v2();
|
||||
|
||||
BOOLEAN Ipc_Init(void);
|
||||
|
||||
BOOLEAN Secure_Init(void);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -275,6 +276,21 @@ _FX void Dll_InitInjected(void)
|
|||
|
||||
Dll_SidStringLen = wcslen(Dll_SidString);
|
||||
|
||||
|
||||
//
|
||||
// break for the debugger, as soon as we have Dll_ImageName
|
||||
//
|
||||
|
||||
if (SbieDll_CheckStringInList(Dll_ImageName, NULL, L"WaitForDebugger")) {
|
||||
//if (SbieDll_GetSettingsForName_bool(NULL, Dll_ImageName, L"WaitForDebugger", FALSE)) {
|
||||
//if (SbieApi_QueryConfBool(NULL, L"WaitForDebuggerAll", FALSE)) {
|
||||
while (!IsDebuggerPresent()) {
|
||||
OutputDebugString(L"Waiting for Debugger\n");
|
||||
Sleep(500);
|
||||
} __debugbreak();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// query Sandboxie home folder
|
||||
//
|
||||
|
@ -332,6 +348,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
|
||||
//
|
||||
|
@ -354,7 +392,7 @@ _FX void Dll_InitInjected(void)
|
|||
Dll_FixWow64Syscall();
|
||||
|
||||
if (ok)
|
||||
ok = File_InitHandles();
|
||||
ok = Handle_Init();
|
||||
|
||||
if (ok)
|
||||
ok = Obj_Init();
|
||||
|
@ -424,7 +462,13 @@ _FX void Dll_InitInjected(void)
|
|||
if (ok)
|
||||
ok = Gui_InitConsole1();
|
||||
|
||||
if (ok)
|
||||
// we need ipc stuff to be up hance we initialize delete stuff second to last
|
||||
if (ok && File_Delete_v2)
|
||||
File_InitDelete_v2();
|
||||
if (ok && Key_Delete_v2)
|
||||
Key_InitDelete_v2();
|
||||
|
||||
if (ok) // Note: Ldr_Init may cause rpcss to be started early
|
||||
ok = Ldr_Init(); // last to initialize
|
||||
|
||||
//
|
||||
|
@ -445,32 +489,6 @@ _FX void Dll_InitInjected(void)
|
|||
|
||||
if (! Dll_RestrictedToken)
|
||||
CustomizeSandbox();
|
||||
|
||||
/*while (! IsDebuggerPresent()) {
|
||||
OutputDebugString(L"BREAK\n");
|
||||
Sleep(500);
|
||||
}
|
||||
__debugbreak();*/
|
||||
|
||||
/*if (_wcsicmp(Dll_ImageName, L"iexplore.exe") == 0) {
|
||||
WCHAR *cmd = GetCommandLine();
|
||||
if (wcsstr(cmd, L"SCODEF")) {
|
||||
|
||||
while (! IsDebuggerPresent()) {
|
||||
OutputDebugString(L"BREAK\n");
|
||||
Sleep(500);
|
||||
}
|
||||
__debugbreak();
|
||||
}
|
||||
}*/
|
||||
|
||||
/*if (_wcsicmp(Dll_ImageName, L"dllhost.exe") == 0) {
|
||||
while (! IsDebuggerPresent()) {
|
||||
OutputDebugString(L"BREAK\n");
|
||||
Sleep(500);
|
||||
}
|
||||
__debugbreak();
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -825,8 +843,10 @@ _FX ULONG_PTR Dll_Ordinal1(
|
|||
//
|
||||
|
||||
int MustRestartProcess = 0;
|
||||
if(Dll_ProcessFlags & SBIE_FLAG_PROCESS_IN_PCA_JOB)
|
||||
if (Dll_ProcessFlags & SBIE_FLAG_PROCESS_IN_PCA_JOB) {
|
||||
if (!SbieApi_QueryConfBool(NULL, L"NoRestartOnPAC", FALSE))
|
||||
MustRestartProcess = 1;
|
||||
}
|
||||
|
||||
else if (Dll_ProcessFlags & SBIE_FLAG_FORCED_PROCESS) {
|
||||
if (SbieApi_QueryConfBool(NULL, L"ForceRestartAll", FALSE)
|
||||
|
|
|
@ -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
|
||||
|
@ -24,6 +24,7 @@
|
|||
#include "dll.h"
|
||||
#include "common/pool.h"
|
||||
#include <stdio.h>
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -282,7 +283,7 @@ _FX THREAD_DATA *Dll_GetTlsData(ULONG *pLastError)
|
|||
_FX void Dll_FreeTlsData(void)
|
||||
{
|
||||
THREAD_DATA *data;
|
||||
ULONG depth, type;
|
||||
ULONG depth, count;
|
||||
|
||||
if (Dll_TlsIndex == TLS_OUT_OF_INDEXES)
|
||||
data = NULL;
|
||||
|
@ -295,12 +296,12 @@ _FX void Dll_FreeTlsData(void)
|
|||
|
||||
for (depth = 0; depth < NAME_BUFFER_DEPTH; ++depth) {
|
||||
|
||||
for (type = 0; type < NAME_BUFFER_COUNT; ++type) {
|
||||
for (count = 0; count < NAME_BUFFER_COUNT; ++count) {
|
||||
|
||||
WCHAR* buf = data->name_buffer[type][depth];
|
||||
WCHAR* buf = data->name_buffer[count][depth];
|
||||
if (buf)
|
||||
Dll_Free(buf);
|
||||
data->name_buffer[type][depth] = NULL;
|
||||
data->name_buffer[count][depth] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,16 +314,38 @@ _FX void Dll_FreeTlsData(void)
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
ALIGNED WCHAR *Dll_GetTlsNameBuffer(
|
||||
THREAD_DATA *data, ULONG which, ULONG size)
|
||||
#ifdef NAME_BUFFER_DEBUG
|
||||
ALIGNED WCHAR *Dll_GetTlsNameBuffer_(THREAD_DATA *data, ULONG which, ULONG size, char* func)
|
||||
#else
|
||||
ALIGNED WCHAR *Dll_GetTlsNameBuffer(THREAD_DATA *data, ULONG which, ULONG size)
|
||||
#endif
|
||||
{
|
||||
WCHAR *old_name_buffer;
|
||||
ULONG old_name_buffer_len;
|
||||
WCHAR **name_buffer;
|
||||
ULONG *name_buffer_len;
|
||||
|
||||
name_buffer = &data->name_buffer [which][data->depth];
|
||||
name_buffer_len = &data->name_buffer_len[which][data->depth];
|
||||
//
|
||||
// since we have more places where we may need a name buffer now
|
||||
// instead of sticking to "which" and doing our best to not reuse a particualr buffer thats still needed
|
||||
// we just increment a counter and take a new buffer reach time we request one
|
||||
//
|
||||
|
||||
if (which >= MISC_NAME_BUFFER)
|
||||
which = MISC_NAME_BUFFER + data->name_buffer_count[data->name_buffer_depth]++;
|
||||
|
||||
#ifdef NAME_BUFFER_DEBUG
|
||||
DbgTrace("Dll_GetTlsNameBuffer, %s, %d\r\n", func, which);
|
||||
#endif
|
||||
|
||||
if (which >= NAME_BUFFER_COUNT - 4)
|
||||
SbieApi_Log(2310, L"%d", which);
|
||||
if (which >= NAME_BUFFER_COUNT) {
|
||||
ExitProcess(-1);
|
||||
}
|
||||
|
||||
name_buffer = &data->name_buffer [which][data->name_buffer_depth];
|
||||
name_buffer_len = &data->name_buffer_len[which][data->name_buffer_depth];
|
||||
|
||||
//
|
||||
// round up the requested size (+ extra padding of some bytes)
|
||||
|
@ -351,7 +374,7 @@ ALIGNED WCHAR *Dll_GetTlsNameBuffer(
|
|||
|
||||
//
|
||||
// debug checks: the name buffer is allocated at least 64 bytes
|
||||
// more than needed. fill these with 0xCC, and check that later
|
||||
// more than needed. fill these with 0xCC, andd check that later
|
||||
//
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
|
@ -379,13 +402,14 @@ ALIGNED void Dll_PushTlsNameBuffer(THREAD_DATA *data)
|
|||
#endif
|
||||
{
|
||||
#ifdef NAME_BUFFER_DEBUG
|
||||
DbgTrace("Dll_PushTlsNameBuffer, %s, %d\r\n", func, data->depth);
|
||||
DbgTrace("Dll_PushTlsNameBuffer, %s, %d\r\n", func, data->name_buffer_depth);
|
||||
#endif
|
||||
|
||||
++data->depth;
|
||||
if (data->depth > NAME_BUFFER_DEPTH - 4)
|
||||
SbieApi_Log(2310, L"%d", data->depth);
|
||||
if (data->depth >= NAME_BUFFER_DEPTH) {
|
||||
++data->name_buffer_depth;
|
||||
data->name_buffer_count[data->name_buffer_depth] = 0; // initialize
|
||||
if (data->name_buffer_depth > NAME_BUFFER_DEPTH - 4)
|
||||
SbieApi_Log(2310, L"%d", data->name_buffer_depth);
|
||||
if (data->name_buffer_depth >= NAME_BUFFER_DEPTH) {
|
||||
ExitProcess(-1);
|
||||
}
|
||||
}
|
||||
|
@ -403,12 +427,12 @@ _FX void Dll_PopTlsNameBuffer(THREAD_DATA *data)
|
|||
#endif
|
||||
{
|
||||
#ifdef NAME_BUFFER_DEBUG
|
||||
DbgTrace("Dll_PopTlsNameBuffer, %s, %d\r\n", func, data->depth-1);
|
||||
DbgTrace("Dll_PopTlsNameBuffer, %s, %d\r\n", func, data->name_buffer_depth-1);
|
||||
#endif
|
||||
|
||||
//
|
||||
// debug checks: the name buffer is allocated at least 64 bytes
|
||||
// more than needed. fill these with 0xCC, and check that later
|
||||
// more than needed. fill these with 0xCC, andd check that later
|
||||
//
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
|
@ -446,14 +470,12 @@ _FX void Dll_PopTlsNameBuffer(THREAD_DATA *data)
|
|||
__debugbreak();
|
||||
}
|
||||
|
||||
// todo: snapshots TMPL_NAME_BUFFER
|
||||
|
||||
}
|
||||
|
||||
#endif // DEBUG_MEMORY
|
||||
|
||||
--data->depth;
|
||||
if (data->depth < 0) {
|
||||
SbieApi_Log(2310, L"%d", data->depth);
|
||||
--data->name_buffer_depth;
|
||||
if (data->name_buffer_depth < 0) {
|
||||
SbieApi_Log(2310, L"%d", data->name_buffer_depth);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,814 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../../common/my_version.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// 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();
|
||||
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);
|
||||
|
||||
HANDLE File_AcquireMutex(const WCHAR* MutexName);
|
||||
void File_ReleaseMutex(HANDLE hMutex);
|
||||
#define FILE_VFS_MUTEX SBIE L"_VFS_Mutex"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// 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, MISC_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_AcquireMutex
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX HANDLE File_AcquireMutex(const WCHAR *MutexName)
|
||||
{
|
||||
HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, MutexName);
|
||||
if (! hMutex)
|
||||
hMutex = CreateMutex(NULL, FALSE, MutexName);
|
||||
if (hMutex)
|
||||
WaitForSingleObject(hMutex, 5000);
|
||||
|
||||
return hMutex;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Scm_ReleaseMutex
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX void File_ReleaseMutex(HANDLE hMutex)
|
||||
{
|
||||
if (hMutex) {
|
||||
|
||||
ReleaseMutex(hMutex);
|
||||
|
||||
CloseHandle(hMutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// File_LoadPathTree_internal
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX BOOLEAN 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 FALSE;
|
||||
|
||||
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);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// File_LoadPathTree
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX BOOLEAN File_LoadPathTree()
|
||||
{
|
||||
HANDLE hMutex = File_AcquireMutex(FILE_VFS_MUTEX);
|
||||
|
||||
EnterCriticalSection(File_PathRoot_CritSec);
|
||||
|
||||
File_LoadPathTree_internal(&File_PathRoot, FILE_PATH_FILE_NAME);
|
||||
|
||||
LeaveCriticalSection(File_PathRoot_CritSec);
|
||||
|
||||
File_ReleaseMutex(hMutex);
|
||||
|
||||
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 BOOLEAN File_MarkDeleted_internal(LIST* Root, const WCHAR* Path)
|
||||
{
|
||||
// 1. remove deleted branche
|
||||
|
||||
LIST* Parent = NULL;
|
||||
PATH_NODE* Node = File_FindPathBranche_internal(Root, Path, &Parent, FALSE);
|
||||
if (Node) {
|
||||
if (Node->flags == FILE_DELETED_FLAG && Node->items.count == 0)
|
||||
return FALSE; // already marked deleted
|
||||
|
||||
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
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// File_MarkDeleted_v2
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX NTSTATUS File_MarkDeleted_v2(const WCHAR* TruePath)
|
||||
{
|
||||
//
|
||||
// add a file or directory to the deleted list
|
||||
//
|
||||
|
||||
HANDLE hMutex = File_AcquireMutex(FILE_VFS_MUTEX);
|
||||
|
||||
EnterCriticalSection(File_PathRoot_CritSec);
|
||||
|
||||
BOOLEAN bSet = File_MarkDeleted_internal(&File_PathRoot, TruePath);
|
||||
|
||||
LeaveCriticalSection(File_PathRoot_CritSec);
|
||||
|
||||
if (bSet) File_SavePathTree();
|
||||
|
||||
File_ReleaseMutex(hMutex);
|
||||
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
|
||||
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(Root, OldTruePath, &OldOldTruePath, TRUE);
|
||||
if (OldOldTruePath) OldTruePath = OldOldTruePath;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
//
|
||||
// List a mapping for the new location
|
||||
//
|
||||
|
||||
HANDLE hMutex = File_AcquireMutex(FILE_VFS_MUTEX);
|
||||
|
||||
EnterCriticalSection(File_PathRoot_CritSec);
|
||||
|
||||
File_SetRelocation_internal(&File_PathRoot, OldTruePath, NewTruePath);
|
||||
|
||||
LeaveCriticalSection(File_PathRoot_CritSec);
|
||||
|
||||
File_SavePathTree();
|
||||
|
||||
File_ReleaseMutex(hMutex);
|
||||
|
||||
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;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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");
|
||||
|
@ -1788,57 +1776,3 @@ _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++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// 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;
|
||||
}
|
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// 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);
|
||||
|
||||
if (File_Delete_v2)
|
||||
{
|
||||
File_RefreshPathTree();
|
||||
|
||||
if(!pRelocation)
|
||||
Dll_PushTlsNameBuffer(TlsData);
|
||||
|
||||
EnterCriticalSection(File_PathRoot_CritSec);
|
||||
|
||||
//
|
||||
// check true path relocation and deleteion for the active state
|
||||
//
|
||||
|
||||
Flags = File_GetPathFlags_internal(&File_PathRoot, TruePath, &Relocation, TRUE); // this requires a name buffer
|
||||
if (FILE_PATH_DELETED(Flags))
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!File_Snapshot)
|
||||
{
|
||||
if (pRelocation) *pRelocation = Relocation; // return a MISC_NAME_BUFFER buffer valid at the current name buffer depth
|
||||
|
||||
goto finish;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle snapshots
|
||||
//
|
||||
|
||||
NTSTATUS status;
|
||||
OBJECT_ATTRIBUTES objattrs;
|
||||
UNICODE_STRING objname;
|
||||
ULONG FileType;
|
||||
|
||||
InitializeObjectAttributes(&objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
|
||||
//
|
||||
// we need a few helper buffers here, to make it efficient we will exploit
|
||||
// an implementation artefact of the TlsNameBuffer mechanism, namely
|
||||
// the property that after a pop the buffers remain valid untill the next push
|
||||
//
|
||||
// so we can pop out of the current frame request a buffer of the required size
|
||||
// and still read from the buffer that was filled in the previosue frame
|
||||
//
|
||||
|
||||
Dll_PushTlsNameBuffer(TlsData);
|
||||
|
||||
WCHAR* TmplRelocation = Relocation;
|
||||
|
||||
for (FILE_SNAPSHOT* Cur_Snapshot = File_Snapshot; Cur_Snapshot != lastSnapshot; Cur_Snapshot = Cur_Snapshot->Parent)
|
||||
{
|
||||
if (TmplRelocation)
|
||||
{
|
||||
//
|
||||
// update the true file name
|
||||
//
|
||||
|
||||
TruePath = Dll_GetTlsNameBuffer(TlsData, TRUE_NAME_BUFFER, (wcslen(TmplRelocation) + 1) * sizeof(WCHAR));
|
||||
wcscpy((WCHAR*)TruePath, TmplRelocation);
|
||||
|
||||
if (CopyPath)
|
||||
{
|
||||
//
|
||||
// update the copy file name
|
||||
//
|
||||
|
||||
Dll_PushTlsNameBuffer(TlsData);
|
||||
|
||||
WCHAR* TruePath2, * CopyPath2;
|
||||
RtlInitUnicodeString(&objname, TmplRelocation);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 complete;
|
||||
}
|
||||
}
|
||||
|
||||
if (File_Delete_v2)
|
||||
{
|
||||
//
|
||||
// check true path relocation and deleteion for the current snapshot
|
||||
//
|
||||
|
||||
TmplRelocation = NULL;
|
||||
Flags = File_GetPathFlags_internal(&Cur_Snapshot->PathRoot, TruePath, &TmplRelocation, TRUE);
|
||||
if(TmplRelocation)
|
||||
Relocation = TmplRelocation;
|
||||
if (FILE_PATH_DELETED(Flags))
|
||||
goto complete;
|
||||
}
|
||||
}
|
||||
|
||||
complete:
|
||||
Dll_PopTlsNameBuffer(TlsData);
|
||||
|
||||
// note: pop leaves the buffers valid we can still use them
|
||||
|
||||
if (pRelocation && Relocation) // return a new TMPL_NAME_BUFFER buffer valid at the current name buffer depth
|
||||
{
|
||||
*pRelocation = Dll_GetTlsNameBuffer(TlsData, TMPL_NAME_BUFFER, (wcslen(Relocation) + 1) * sizeof(WCHAR));
|
||||
wcscpy(*pRelocation, Relocation);
|
||||
}
|
||||
|
||||
finish:
|
||||
|
||||
if (File_Delete_v2)
|
||||
{
|
||||
LeaveCriticalSection(File_PathRoot_CritSec);
|
||||
|
||||
if(!pRelocation)
|
||||
Dll_PopTlsNameBuffer(TlsData);
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
|
@ -66,7 +66,7 @@ static ULONG Gdi_CreateScalableFontResourceW(
|
|||
static void Gdi_AddFontsInBox(void);
|
||||
|
||||
static void Gdi_AddFontsInBox_2(
|
||||
HANDLE hFontsDir, void *buf8k, WCHAR *WinFonts);
|
||||
HANDLE hFontsDir, WCHAR *WinFonts);
|
||||
|
||||
static int Gdi_EnumFontFamiliesExA(
|
||||
HDC hdc, void *lpLogfont, void *lpEnumFontFamExProc,
|
||||
|
@ -618,15 +618,13 @@ _FX void Gdi_AddFontsInBox(void)
|
|||
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
WCHAR *path1 = Dll_AllocTemp(8192);
|
||||
BOOLEAN is_copy = FALSE;
|
||||
NTSTATUS status = SbieDll_GetHandlePath(hFile, path1, &is_copy);
|
||||
NTSTATUS status = SbieDll_GetHandlePath(hFile, NULL, &is_copy);
|
||||
if (NT_SUCCESS(status) && is_copy) {
|
||||
|
||||
Gdi_AddFontsInBox_2(hFile, path1, WinFonts);
|
||||
Gdi_AddFontsInBox_2(hFile, WinFonts);
|
||||
}
|
||||
|
||||
Dll_Free(path1);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
|
@ -642,7 +640,7 @@ _FX void Gdi_AddFontsInBox(void)
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX void Gdi_AddFontsInBox_2(HANDLE hFontsDir, void *buf8k, WCHAR *WinFonts)
|
||||
_FX void Gdi_AddFontsInBox_2(HANDLE hFontsDir, WCHAR *WinFonts)
|
||||
{
|
||||
NTSTATUS status;
|
||||
FILE_DIRECTORY_INFORMATION *info;
|
||||
|
@ -651,6 +649,8 @@ _FX void Gdi_AddFontsInBox_2(HANDLE hFontsDir, void *buf8k, WCHAR *WinFonts)
|
|||
ULONG WinFonts_len = wcslen(WinFonts);
|
||||
WinFonts[WinFonts_len] = L'\\';
|
||||
|
||||
WCHAR *buf8k = Dll_AllocTemp(8192);
|
||||
|
||||
while (1) {
|
||||
|
||||
info = (FILE_DIRECTORY_INFORMATION *)buf8k;
|
||||
|
@ -680,6 +680,8 @@ _FX void Gdi_AddFontsInBox_2(HANDLE hFontsDir, void *buf8k, WCHAR *WinFonts)
|
|||
info = (FILE_DIRECTORY_INFORMATION *)next_entry;
|
||||
}
|
||||
}
|
||||
|
||||
Dll_Free(buf8k);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Handle
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define NOGDI
|
||||
#include "dll.h"
|
||||
#include "handle.h"
|
||||
#include <stdio.h>
|
||||
#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);
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#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 */
|
|
@ -184,7 +184,6 @@ _FX BOOLEAN Hook_Tramp_CountBytes(
|
|||
void *SysProc, ULONG *ByteCount, BOOLEAN is64, BOOLEAN probe)
|
||||
{
|
||||
UCHAR *addr = (UCHAR *)SysProc;
|
||||
//ULONG needlen = (is64 == 9 ? 13 : (is64 ? 12 : (File_TrusteerLoaded()?6:5)));
|
||||
ULONG needlen = (is64 ? 12 : 5);
|
||||
ULONG copylen = 0;
|
||||
|
||||
|
|
|
@ -404,6 +404,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);
|
||||
|
@ -550,6 +551,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;
|
||||
|
@ -690,6 +706,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))
|
||||
|
@ -713,11 +744,23 @@ check_sandbox_prefix:
|
|||
|
||||
*OutCopyPath = name;
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
*name = L'\0';
|
||||
|
||||
//
|
||||
|
@ -908,6 +951,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
|
||||
|
@ -3450,15 +3496,11 @@ _FX BOOLEAN Ipc_IsKnownDllInSandbox(
|
|||
if (NT_SUCCESS(status)) {
|
||||
|
||||
BOOLEAN IsBoxedPath;
|
||||
WCHAR *path8k = Dll_AllocTemp(8192 * sizeof(WCHAR));
|
||||
|
||||
status = SbieDll_GetHandlePath(handle, path8k, &IsBoxedPath);
|
||||
status = SbieDll_GetHandlePath(handle, NULL, &IsBoxedPath);
|
||||
|
||||
if (NT_SUCCESS(status) && IsBoxedPath)
|
||||
is_known_dll_in_sandbox = TRUE;
|
||||
|
||||
Dll_Free(path8k);
|
||||
|
||||
NtClose(handle);
|
||||
}
|
||||
|
||||
|
@ -3984,6 +4026,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)) {
|
||||
|
||||
|
|
|
@ -24,10 +24,11 @@
|
|||
#define NOGDI
|
||||
#include "dll.h"
|
||||
#include "obj.h"
|
||||
#include "handle.h"
|
||||
#include "core/svc/FileWire.h"
|
||||
#include "core/drv/api_defs.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
@ -306,6 +307,8 @@ static const WCHAR *Key_Wow6432Node = L"\\Wow6432Node\\";
|
|||
|
||||
static BOOLEAN Key_UseObjectNames = FALSE;
|
||||
|
||||
BOOLEAN Key_Delete_v2 = FALSE;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Debug Prints
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -338,6 +341,7 @@ static BOOLEAN Key_UseObjectNames = FALSE;
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "key_del.c"
|
||||
#include "key_merge.c"
|
||||
#include "key_util.c"
|
||||
|
||||
|
@ -358,6 +362,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);
|
||||
|
||||
|
@ -433,6 +439,7 @@ _FX NTSTATUS Key_GetName(
|
|||
ULONG length;
|
||||
WCHAR *name;
|
||||
ULONG objname_len;
|
||||
BOOLEAN is_boxed_path;
|
||||
|
||||
*OutTruePath = NULL;
|
||||
*OutCopyPath = NULL;
|
||||
|
@ -587,6 +594,8 @@ _FX NTSTATUS Key_GetName(
|
|||
// and restore the "\REGISTRY" prefix that would have been lost.
|
||||
//
|
||||
|
||||
is_boxed_path = FALSE;
|
||||
|
||||
check_sandbox_prefix:
|
||||
|
||||
if (length >= Dll_BoxKeyPathLen &&
|
||||
|
@ -598,6 +607,7 @@ check_sandbox_prefix:
|
|||
length -= Dll_BoxKeyPathLen - Key_RegistryLen;
|
||||
if (OutIsBoxedPath)
|
||||
*OutIsBoxedPath = TRUE;
|
||||
is_boxed_path = TRUE;
|
||||
|
||||
goto check_sandbox_prefix;
|
||||
}
|
||||
|
@ -651,6 +661,33 @@ check_sandbox_prefix:
|
|||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// if this is a unboxed path, and we opened it by object,
|
||||
// check path relocation and update true path accordingly.
|
||||
//
|
||||
|
||||
if (!is_boxed_path && RootDirectory) {
|
||||
|
||||
name = Handle_GetRelocationPath(RootDirectory, objname_len);
|
||||
if (name) {
|
||||
|
||||
*OutTruePath = name;
|
||||
|
||||
name = (*OutTruePath) + wcslen(*OutTruePath);
|
||||
|
||||
if (objname_len) {
|
||||
|
||||
*name = L'\\';
|
||||
++name;
|
||||
memcpy(name, ObjectName->Buffer, objname_len);
|
||||
|
||||
name += objname_len / sizeof(WCHAR);
|
||||
}
|
||||
|
||||
*name = L'\0';
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// now create the copy path, which is the box prefix prepended
|
||||
// to the true path that we have. note that the copy path will
|
||||
|
@ -1096,6 +1133,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,
|
||||
|
@ -1120,6 +1192,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,
|
||||
|
@ -1147,6 +1230,8 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
|
|||
|
||||
CopyPathCreated = FALSE;
|
||||
TruePathExists = FALSE;
|
||||
OriginalPath = NULL;
|
||||
TrueOpened = FALSE;
|
||||
|
||||
TlsData->key_NtCreateKey_lock = TRUE;
|
||||
|
||||
|
@ -1226,6 +1311,8 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
|
|||
}
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) TrueOpened = TRUE;
|
||||
|
||||
__leave;
|
||||
|
||||
#undef KEY_READ_WOW64
|
||||
|
@ -1257,6 +1344,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
|
||||
|
@ -1264,8 +1353,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)) {
|
||||
|
||||
//
|
||||
|
@ -1351,9 +1439,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) {
|
||||
|
||||
|
@ -1418,6 +1509,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
|
||||
|
@ -1465,6 +1578,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
|
||||
|
@ -1476,9 +1591,13 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
|
|||
// the reason is that if NtSetValueKey has to re-open this key
|
||||
// for write access, it would not be able to pass the WOW64 flag
|
||||
//
|
||||
// this special case makes IMHO no sense, wow registry redirection
|
||||
// acts only on specific paths, and our sanboxed paths do not fall
|
||||
// into that category, hence thay dont need KEY_WOW64_xxKEY flags!
|
||||
//
|
||||
|
||||
if (OriginalDesiredAccess & (KEY_WOW64_32KEY | KEY_WOW64_64KEY))
|
||||
goto SkipReadOnlyCheck;
|
||||
//if (OriginalDesiredAccess & (KEY_WOW64_32KEY | KEY_WOW64_64KEY))
|
||||
// goto SkipReadOnlyCheck;
|
||||
|
||||
if (((DesiredAccess & ~MAXIMUM_ALLOWED) & KEY_DENIED_ACCESS) == 0) {
|
||||
|
||||
|
@ -1615,6 +1734,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;
|
||||
}
|
||||
|
@ -1628,6 +1749,20 @@ SkipReadOnlyCheck:
|
|||
if (CopyPathCreated)
|
||||
Key_DiscardMergeByPath(TruePath, TRUE);
|
||||
|
||||
//
|
||||
// Relocation, if we opened a relocated location we need to
|
||||
// store the original true path for the Key_GetName function
|
||||
//
|
||||
|
||||
if (TrueOpened && OriginalPath) {
|
||||
|
||||
Handle_SetRelocationPath(*KeyHandle, OriginalPath);
|
||||
}
|
||||
|
||||
//
|
||||
// finish
|
||||
//
|
||||
|
||||
Dll_PopTlsNameBuffer(TlsData);
|
||||
|
||||
TlsData->key_NtCreateKey_lock = FALSE;
|
||||
|
@ -1655,6 +1790,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
|
||||
|
@ -1703,6 +1866,7 @@ _FX NTSTATUS Key_CreatePath(
|
|||
|
||||
if (NT_SUCCESS(status)) {
|
||||
|
||||
if (!Key_Delete_v2)
|
||||
if (disp == REG_OPENED_EXISTING_KEY) {
|
||||
if (Key_CheckDeletedKey(handle)) {
|
||||
|
||||
|
@ -2044,7 +2208,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;
|
||||
|
||||
|
@ -2183,6 +2347,39 @@ _FX NTSTATUS Key_MarkDeletedAndClose(HANDLE KeyHandle)
|
|||
// mark key deleted by setting its last write time information
|
||||
//
|
||||
|
||||
if (Key_Delete_v2) {
|
||||
|
||||
THREAD_DATA *TlsData = Dll_GetTlsData(NULL);
|
||||
|
||||
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(
|
||||
|
@ -2194,6 +2391,7 @@ _FX NTSTATUS Key_MarkDeletedAndClose(HANDLE KeyHandle)
|
|||
//
|
||||
|
||||
Key_DiscardMergeByHandle(TlsData, KeyHandle, TRUE);
|
||||
}
|
||||
|
||||
//
|
||||
// close key handle
|
||||
|
@ -2308,14 +2506,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 {
|
||||
|
||||
//
|
||||
|
@ -2342,6 +2544,8 @@ _FX NTSTATUS Key_NtDeleteValueKey(
|
|||
}
|
||||
}
|
||||
|
||||
Dll_PopTlsNameBuffer(TlsData);
|
||||
|
||||
SetLastError(LastError);
|
||||
return status;
|
||||
}
|
||||
|
@ -2496,6 +2700,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.
|
||||
|
@ -2510,26 +2724,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)
|
||||
{
|
||||
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
|
||||
|
@ -2602,11 +2811,17 @@ _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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__leave;
|
||||
|
@ -2790,11 +3005,17 @@ _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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__leave;
|
||||
|
@ -3189,12 +3410,17 @@ _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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__leave;
|
||||
|
@ -3545,12 +3771,27 @@ _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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__leave;
|
||||
|
@ -4069,10 +4310,163 @@ _FX HANDLE Key_GetTrueHandle(HANDLE KeyHandle, BOOLEAN *pIsOpenPath)
|
|||
_FX NTSTATUS Key_NtRenameKey(
|
||||
HANDLE KeyHandle, UNICODE_STRING *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, MISC_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();
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
goto finish;
|
||||
|
||||
//
|
||||
// check if the target key already exists in the true path
|
||||
//
|
||||
|
||||
WCHAR* NewTruePath2 = NewTruePath;
|
||||
WCHAR* OldTruePath = Key_GetRelocation(NewTruePath);
|
||||
if (OldTruePath)
|
||||
NewTruePath2 = OldTruePath;
|
||||
|
||||
RtlInitUnicodeString(&objname, NewTruePath2);
|
||||
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_NOT_FOUND;
|
||||
|
||||
File_NtCloseImpl(handle);
|
||||
}
|
||||
|
||||
if (status != STATUS_OBJECT_NAME_NOT_FOUND)
|
||||
goto finish;
|
||||
|
||||
//
|
||||
// rename the key ensuring we wil have a boxed copy
|
||||
// try renaming if it fails with access denided try again with a new handle
|
||||
//
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// check if the true path exists and if so mark path deleted
|
||||
//
|
||||
|
||||
BOOLEAN TrueExists = FALSE;
|
||||
|
||||
WCHAR* TruePath2 = TruePath;
|
||||
|
||||
OldTruePath = Key_GetRelocation(TruePath);
|
||||
if (OldTruePath)
|
||||
TruePath2 = OldTruePath;
|
||||
|
||||
RtlInitUnicodeString(&objname, TruePath2);
|
||||
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);
|
||||
}
|
||||
|
||||
//
|
||||
// set the redirection information
|
||||
//
|
||||
|
||||
if (TrueExists) {
|
||||
|
||||
Key_SetRelocation(TruePath, NewTruePath);
|
||||
}
|
||||
|
||||
//*TruePathSlash = L'\0';
|
||||
//Key_DiscardMergeByPath(TruePath, TRUE); // fix-me: act on Key_MergeCacheList
|
||||
//*TruePathSlash = L'\\';
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
finish:
|
||||
|
||||
Dll_PopTlsNameBuffer(TlsData);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Key_NtSaveKey
|
||||
|
@ -4082,7 +4476,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../../common/my_version.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// 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;
|
||||
|
||||
BOOLEAN Key_RegPaths_Loaded = FALSE;
|
||||
|
||||
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);
|
||||
BOOLEAN 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);
|
||||
BOOLEAN File_MarkDeleted_internal(LIST* Root, const WCHAR* Path);
|
||||
VOID File_SetRelocation_internal(LIST* Root, const WCHAR* OldTruePath, const WCHAR* NewTruePath);
|
||||
|
||||
HANDLE File_AcquireMutex(const WCHAR* MutexName);
|
||||
void File_ReleaseMutex(HANDLE hMutex);
|
||||
#define KEY_VCM_MUTEX SBIE L"_VCM_Mutex"
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// 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()
|
||||
{
|
||||
HANDLE hMutex = File_AcquireMutex(KEY_VCM_MUTEX);
|
||||
|
||||
EnterCriticalSection(Key_PathRoot_CritSec);
|
||||
|
||||
Key_RegPaths_Loaded = File_LoadPathTree_internal(&Key_PathRoot, KEY_PATH_FILE_NAME);
|
||||
|
||||
LeaveCriticalSection(Key_PathRoot_CritSec);
|
||||
|
||||
File_ReleaseMutex(hMutex);
|
||||
|
||||
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
|
||||
//
|
||||
|
||||
HANDLE hMutex = File_AcquireMutex(KEY_VCM_MUTEX);
|
||||
|
||||
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);
|
||||
|
||||
BOOLEAN bSet = File_MarkDeleted_internal(&Key_PathRoot, FullPath);
|
||||
|
||||
LeaveCriticalSection(Key_PathRoot_CritSec);
|
||||
|
||||
if (bSet) Key_SavePathTree();
|
||||
|
||||
File_ReleaseMutex(hMutex);
|
||||
|
||||
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)
|
||||
{
|
||||
//
|
||||
// List a mapping for the new location
|
||||
//
|
||||
|
||||
HANDLE hMutex = File_AcquireMutex(KEY_VCM_MUTEX);
|
||||
|
||||
EnterCriticalSection(Key_PathRoot_CritSec);
|
||||
|
||||
File_SetRelocation_internal(&Key_PathRoot, OldTruePath, NewTruePath);
|
||||
|
||||
LeaveCriticalSection(Key_PathRoot_CritSec);
|
||||
|
||||
Key_SavePathTree();
|
||||
|
||||
File_ReleaseMutex(hMutex);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
@ -36,6 +37,7 @@ typedef struct _KEY_MERGE {
|
|||
|
||||
BOOLEAN subkeys_merged;
|
||||
LARGE_INTEGER last_write_time;
|
||||
ULONGLONG last_paths_version;
|
||||
LIST subkeys;
|
||||
|
||||
ULONG last_index;
|
||||
|
@ -196,6 +198,7 @@ _FX NTSTATUS Key_Merge(
|
|||
// the same key path, so we are going to use it.
|
||||
//
|
||||
|
||||
if(Key_PathsVersion == merge->last_paths_version)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -203,7 +206,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);
|
||||
|
||||
|
@ -225,11 +228,13 @@ _FX NTSTATUS Key_Merge(
|
|||
merge->ticks = ticks_now;
|
||||
// merge->cant_merge = FALSE; // memzero takes care of this
|
||||
|
||||
merge->last_paths_version = Key_PathsVersion;
|
||||
|
||||
merge->name_len = TruePath_len;
|
||||
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);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -237,6 +242,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);
|
||||
|
@ -319,6 +325,7 @@ _FX NTSTATUS Key_OpenForMerge(
|
|||
ULONG len;
|
||||
HANDLE TrueHandle;
|
||||
ULONG mp_flags;
|
||||
const WCHAR* OriginalPath = NULL;
|
||||
|
||||
*out_TrueMerge = NULL;
|
||||
*out_CopyHandle = NULL;
|
||||
|
@ -365,6 +372,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
|
||||
|
@ -382,6 +390,9 @@ _FX NTSTATUS Key_OpenForMerge(
|
|||
// if we couldn't find a copy key, indicate there is nothing to merge
|
||||
//
|
||||
|
||||
if (Key_Delete_v2 && Key_HasDeleted_v2(TruePath))
|
||||
status = STATUS_SUCCESS;
|
||||
else
|
||||
status = STATUS_BAD_INITIAL_PC;
|
||||
}
|
||||
|
||||
|
@ -390,6 +401,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
|
||||
|
@ -418,7 +441,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);
|
||||
|
@ -442,7 +465,7 @@ _FX NTSTATUS Key_OpenForMerge(
|
|||
//
|
||||
|
||||
if (use_rule_specificity)
|
||||
Key_MergeCache(NULL, &info.LastWriteTime, TruePath, out_TrueMerge);
|
||||
Key_MergeCache(NULL, &info.LastWriteTime, OriginalPath ? OriginalPath : TruePath, out_TrueMerge);
|
||||
}
|
||||
|
||||
if (! NT_SUCCESS(status)) {
|
||||
|
@ -637,7 +660,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;
|
||||
}
|
||||
|
@ -660,6 +683,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
|
||||
|
@ -837,6 +861,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
|
||||
|
@ -936,6 +966,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
|
||||
//
|
||||
|
@ -973,7 +1009,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
|
||||
|
@ -991,6 +1027,7 @@ _FX NTSTATUS Key_MergeSubkeys(
|
|||
}
|
||||
|
||||
merge->last_write_time.QuadPart = info->LastWriteTime.QuadPart;
|
||||
merge->last_paths_version = Key_PathsVersion;
|
||||
|
||||
if (! TrueMerge)
|
||||
goto TrueHandleFinish;
|
||||
|
@ -1071,6 +1108,7 @@ TrueHandleFinish:
|
|||
info->ClassOffset != -1 ||
|
||||
info->ClassLength);
|
||||
|
||||
if (!Key_Delete_v2)
|
||||
if (IS_DELETE_MARK(&info->LastWriteTime))
|
||||
subkey_deleted = TRUE;
|
||||
else
|
||||
|
@ -1097,7 +1135,8 @@ TrueHandleFinish:
|
|||
if (subkey->TitleOrClass)
|
||||
subkey2->TitleOrClass = subkey->TitleOrClass;
|
||||
}
|
||||
subkey_deleted = TRUE;
|
||||
Dll_Free(subkey);
|
||||
subkey = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1142,7 +1181,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);
|
||||
|
@ -1234,6 +1273,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
|
||||
|
@ -1488,7 +1528,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);
|
||||
}
|
||||
|
|
|
@ -45,12 +45,6 @@ static NTSTATUS Obj_NtQueryVirtualMemory(
|
|||
SIZE_T Length,
|
||||
SIZE_T *ResultLength);
|
||||
|
||||
static NTSTATUS Obj_NtQueryInformationProcess(
|
||||
HANDLE ProcessHandle,
|
||||
PROCESSINFOCLASS ProcessInformationClass,
|
||||
PVOID ProcessInformation,
|
||||
ULONG ProcessInformationLength,
|
||||
PULONG ReturnLength);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Variables
|
||||
|
@ -61,8 +55,6 @@ static P_NtQueryObject __sys_NtQueryObject = NULL;
|
|||
|
||||
P_NtQueryVirtualMemory __sys_NtQueryVirtualMemory = NULL;
|
||||
|
||||
P_NtQueryInformationProcess __sys_NtQueryInformationProcess = NULL;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Obj_Init
|
||||
|
@ -76,7 +68,6 @@ _FX BOOLEAN Obj_Init(void)
|
|||
#else
|
||||
SBIEDLL_HOOK(Obj_,NtQueryObject);
|
||||
SBIEDLL_HOOK(Obj_,NtQueryVirtualMemory);
|
||||
SBIEDLL_HOOK(Obj_,NtQueryInformationProcess);
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -411,42 +402,3 @@ finish:
|
|||
SetLastError(LastError);
|
||||
return status;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Obj_NtQueryVirtualMemory
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX NTSTATUS Obj_NtQueryInformationProcess(
|
||||
HANDLE ProcessHandle,
|
||||
PROCESSINFOCLASS ProcessInformationClass,
|
||||
PVOID ProcessInformation,
|
||||
ULONG ProcessInformationLength,
|
||||
PULONG ReturnLength)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG outlen;
|
||||
|
||||
status = __sys_NtQueryInformationProcess(
|
||||
ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, &outlen);
|
||||
|
||||
if (ProcessInformationClass == ProcessImageFileName && ProcessInformation != NULL)
|
||||
{
|
||||
//
|
||||
// since file paths are always shorter without the sandbox prefix we can keep this simple
|
||||
//
|
||||
|
||||
ULONG tmplen;
|
||||
PUNICODE_STRING fileName = (PUNICODE_STRING)ProcessInformation;
|
||||
|
||||
tmplen = File_NtQueryObjectName(fileName, fileName->MaximumLength);
|
||||
|
||||
if (tmplen)
|
||||
outlen = sizeof(UNICODE_STRING) + tmplen;
|
||||
}
|
||||
|
||||
if (ReturnLength)
|
||||
*ReturnLength = outlen;
|
||||
|
||||
return status;
|
||||
}
|
|
@ -291,7 +291,7 @@ static P_WinExec __sys_WinExec = NULL;
|
|||
static P_RunSetupCommandW __sys_RunSetupCommandW = NULL;
|
||||
|
||||
static P_NtSetInformationProcess __sys_NtSetInformationProcess = NULL;
|
||||
static P_NtQueryInformationProcess __sys_NtQueryInformationProcess = NULL;
|
||||
P_NtQueryInformationProcess __sys_NtQueryInformationProcess = NULL;
|
||||
|
||||
static P_NtCreateProcessEx __sys_NtCreateProcessEx = NULL;
|
||||
|
||||
|
@ -2766,6 +2766,17 @@ _FX NTSTATUS Proc_NtQueryInformationProcess(
|
|||
}
|
||||
}
|
||||
|
||||
/*if (ProcessInformationClass == ProcessImageFileName && ProcessInformation != NULL) {
|
||||
|
||||
ULONG tmplen;
|
||||
PUNICODE_STRING fileName = (PUNICODE_STRING)ProcessInformation;
|
||||
|
||||
tmplen = File_NtQueryObjectName(fileName, fileName->MaximumLength);
|
||||
|
||||
if (tmplen)
|
||||
outlen = sizeof(UNICODE_STRING) + tmplen;
|
||||
}*/
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,10 @@
|
|||
#include "core/drv/api_defs.h"
|
||||
#include "core/svc/msgids.h"
|
||||
#include "common/my_version.h"
|
||||
|
||||
//#include "core/low/lowdata.h"
|
||||
//
|
||||
//extern SBIELOW_DATA* SbieApi_data;
|
||||
//#define SBIELOW_CALL(x) ((P_##x)&SbieApi_data->x##_code)
|
||||
|
||||
#pragma optimize("",off)
|
||||
|
||||
|
@ -141,11 +144,30 @@ _FX NTSTATUS SbieApi_Ioctl(ULONG64 *parms)
|
|||
// processing a request before sending the next request
|
||||
//
|
||||
|
||||
extern P_NtDeviceIoControlFile __sys_NtDeviceIoControlFile;
|
||||
if (__sys_NtDeviceIoControlFile) {
|
||||
|
||||
//
|
||||
// once NtDeviceIoControlFile is hooked, bypass it
|
||||
//
|
||||
|
||||
status = __sys_NtDeviceIoControlFile(
|
||||
SbieApi_DeviceHandle, NULL, NULL, NULL, &MyIoStatusBlock,
|
||||
API_SBIEDRV_CTLCODE, parms, sizeof(ULONG64) * 8, NULL, 0);
|
||||
|
||||
} else {
|
||||
|
||||
status = NtDeviceIoControlFile(
|
||||
SbieApi_DeviceHandle, NULL, NULL, NULL, &MyIoStatusBlock,
|
||||
API_SBIEDRV_CTLCODE, parms, sizeof(ULONG64) * 8, NULL, 0);
|
||||
}
|
||||
|
||||
// that would be even better but would only work in the native case
|
||||
//status = SBIELOW_CALL(NtDeviceIoControlFile)(
|
||||
// SbieApi_DeviceHandle, NULL, NULL, NULL, &MyIoStatusBlock,
|
||||
// API_SBIEDRV_CTLCODE, parms, sizeof(ULONG64) * 8, NULL, 0);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "handle.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Service Control Manager
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -238,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;
|
||||
}
|
||||
|
||||
|
@ -259,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -422,6 +422,16 @@ _FX NTSTATUS SysInfo_GetJobName(OBJECT_ATTRIBUTES* ObjectAttributes, WCHAR** Out
|
|||
|
||||
*OutCopyPath = name;
|
||||
|
||||
//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;
|
||||
|
||||
|
@ -430,6 +440,8 @@ _FX NTSTATUS SysInfo_GetJobName(OBJECT_ATTRIBUTES* ObjectAttributes, WCHAR** Out
|
|||
|
||||
wmemcpy(name, objname_buf, objname_len);
|
||||
name += objname_len;
|
||||
}
|
||||
|
||||
*name = L'\0';
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
|
|
@ -1458,8 +1458,7 @@ _FX NTSTATUS Conf_Api_Reload(PROCESS *proc, ULONG64 *parms)
|
|||
}
|
||||
}
|
||||
|
||||
BOOLEAN obj_filter_enabled = Conf_Get_Boolean(NULL, L"EnableObjectFiltering", 0, FALSE);
|
||||
extern BOOLEAN Obj_CallbackInstalled;
|
||||
BOOLEAN obj_filter_enabled = Conf_Get_Boolean(NULL, L"EnableObjectFiltering", 0, TRUE);
|
||||
if (Obj_CallbackInstalled != obj_filter_enabled && Driver_OsVersion > DRIVER_WINDOWS_VISTA) {
|
||||
if (obj_filter_enabled) {
|
||||
Obj_Load_Filter();
|
||||
|
|
|
@ -615,6 +615,11 @@ void* Driver_FindMissingService(const char* ProcName, int prmcnt)
|
|||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Driver_FindMissingServices
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX BOOLEAN Driver_FindMissingServices(void)
|
||||
{
|
||||
#ifdef OLD_DDK
|
||||
|
|
|
@ -267,6 +267,8 @@ _FX void Log_Msg_Process(
|
|||
ULONG session_id,
|
||||
HANDLE process_id)
|
||||
{
|
||||
DbgPrint("Sbie MSG_%d: %S; %S\r\n", (error_code & 0xFFFF), string1, string2);
|
||||
|
||||
ULONG facility = (error_code >> 16) & 0x0F;
|
||||
if (facility & MSG_FACILITY_EVENT)
|
||||
Log_Event_Msg(error_code, string1, string2);
|
||||
|
|
|
@ -644,7 +644,6 @@ _FX POBJECT_TYPE Obj_GetTypeObjectType(void)
|
|||
(POBJECT_TYPE *)(ptr + i + 7 + offset);
|
||||
}
|
||||
}
|
||||
DbgPrint("pObTypeIndexTable = %p\n", pObTypeIndexTable);
|
||||
}
|
||||
#else ! _WIN64
|
||||
UCHAR k = 0;
|
||||
|
@ -661,9 +660,8 @@ _FX POBJECT_TYPE Obj_GetTypeObjectType(void)
|
|||
pObTypeIndexTable = (POBJECT_TYPE *)*ptr2;
|
||||
}
|
||||
}
|
||||
|
||||
#endif _WIN64
|
||||
|
||||
//DbgPrint("pObTypeIndexTable = %p\n", pObTypeIndexTable);
|
||||
}
|
||||
|
||||
if (! pObTypeIndexTable) {
|
||||
|
|
|
@ -82,7 +82,6 @@ const ULONG tzuk = 'xobs';
|
|||
// WinMain
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
ULONG Dll_Windows = 0;
|
||||
|
||||
int WinMain(
|
||||
HINSTANCE hInstance,
|
||||
|
@ -97,9 +96,6 @@ int WinMain(
|
|||
_Ntdll = GetModuleHandle(L"ntdll.dll");
|
||||
_Kernel32 = GetModuleHandle(L"kernel32.dll");
|
||||
GetSystemInfo(&_SystemInfo);
|
||||
if (GetProcAddress(_Ntdll, "LdrFastFailInLoaderCallout")) {
|
||||
Dll_Windows = 10;
|
||||
}
|
||||
|
||||
WCHAR *cmdline = GetCommandLine();
|
||||
if (cmdline) {
|
||||
|
|
|
@ -69,7 +69,7 @@ void CSimpleListModel::Sync(QList<QVariantMap> List)
|
|||
Changed = true;
|
||||
ColValue.Raw = Value;
|
||||
|
||||
//ColValue.Formated =
|
||||
//ColValue.Formatted =
|
||||
}
|
||||
|
||||
if(State != Changed)
|
||||
|
@ -195,7 +195,7 @@ QVariant CListItemModel::Data(const QModelIndex &index, int role, int section) c
|
|||
case Qt::DisplayRole:
|
||||
{
|
||||
SListNode::SValue& Value = pNode->Values[section];
|
||||
return Value.Formated.isValid() ? Value.Formated : Value.Raw;
|
||||
return Value.Formatted.isValid() ? Value.Formatted : Value.Raw;
|
||||
}
|
||||
case Qt::EditRole: // sort role
|
||||
{
|
||||
|
|
|
@ -56,7 +56,7 @@ protected:
|
|||
struct SValue
|
||||
{
|
||||
QVariant Raw;
|
||||
QVariant Formated;
|
||||
QVariant Formatted;
|
||||
};
|
||||
QVector<SValue> Values;
|
||||
};
|
||||
|
|
|
@ -110,7 +110,7 @@ void CSimpleTreeModel::Sync(const QMap<QVariant, QVariantMap>& List)
|
|||
Changed = true;
|
||||
ColValue.Raw = Value;
|
||||
|
||||
//ColValue.Formated =
|
||||
//ColValue.Formatted =
|
||||
}
|
||||
|
||||
if(State != Changed)
|
||||
|
@ -385,7 +385,7 @@ QVariant CTreeItemModel::NodeData(STreeNode* pNode, int role, int section) const
|
|||
case Qt::DisplayRole:
|
||||
{
|
||||
STreeNode::SValue& Value = pNode->Values[section];
|
||||
return Value.Formated.isValid() ? Value.Formated : Value.Raw;
|
||||
return Value.Formatted.isValid() ? Value.Formatted : Value.Raw;
|
||||
}
|
||||
case Qt::EditRole: // sort role
|
||||
{
|
||||
|
|
|
@ -80,7 +80,7 @@ protected:
|
|||
{
|
||||
QVariant Raw;
|
||||
QVariant SortKey;
|
||||
QVariant Formated;
|
||||
QVariant Formatted;
|
||||
};
|
||||
QVector<SValue> Values;
|
||||
};
|
||||
|
|
|
@ -106,7 +106,7 @@ CBoxBorder::CBoxBorder(CSbieAPI* pApi, QObject* parent) : QObject(parent)
|
|||
SetLayeredWindowAttributes(m->BorderWnd, 0, 192, LWA_ALPHA);
|
||||
::ShowWindow(m->BorderWnd, SW_HIDE);
|
||||
|
||||
m_uTimerID = startTimer(10);
|
||||
m_uTimerID = startTimer(100);
|
||||
}
|
||||
|
||||
CBoxBorder::~CBoxBorder()
|
||||
|
|
|
@ -119,6 +119,13 @@ void CSandBox::UpdateDetails()
|
|||
{
|
||||
}
|
||||
|
||||
void CSandBox::SetBoxPaths(const QString& FilePath, const QString& RegPath, const QString& IpcPath)
|
||||
{
|
||||
m_FilePath = FilePath;
|
||||
m_RegPath = RegPath;
|
||||
m_IpcPath = IpcPath;
|
||||
}
|
||||
|
||||
SB_STATUS CSandBox::RunStart(const QString& Command, bool Elevated)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
|
@ -140,7 +147,7 @@ SB_STATUS CSandBox::TerminateAll()
|
|||
|
||||
bool CSandBox::IsEmpty() const
|
||||
{
|
||||
return !QDir(m_FilePath).exists();
|
||||
return !QFile::exists(m_FilePath);
|
||||
}
|
||||
|
||||
SB_PROGRESS CSandBox::CleanBox()
|
||||
|
@ -327,6 +334,8 @@ struct SBoxDataFile
|
|||
|
||||
QList<SBoxDataFile> CSandBox__BoxDataFiles = QList<SBoxDataFile>()
|
||||
<< SBoxDataFile("RegHive", true, false)
|
||||
<< SBoxDataFile("RegPaths.dat", false, false)
|
||||
<< SBoxDataFile("FilePaths.dat", false, true)
|
||||
;
|
||||
|
||||
bool CSandBox::IsInitialized() const
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
|
||||
virtual void UpdateDetails();
|
||||
|
||||
virtual void SetBoxPaths(const QString& FilePath, const QString& RegPath, const QString& IpcPath);
|
||||
virtual QString GetFileRoot() const { return m_FilePath; }
|
||||
virtual QString GetRegRoot() const { return m_RegPath; }
|
||||
virtual QString GetIpcRoot() const { return m_IpcPath; }
|
||||
|
@ -54,6 +55,7 @@ public:
|
|||
virtual SB_STATUS RunSandboxed(const QString& Command);
|
||||
virtual SB_STATUS TerminateAll();
|
||||
|
||||
virtual void OpenBox() {}
|
||||
virtual void CloseBox() {}
|
||||
|
||||
virtual bool IsEnabled() const { return m_IsEnabled; }
|
||||
|
|
|
@ -129,7 +129,9 @@ CSbieAPI::CSbieAPI(QObject* parent) : QThread(parent)
|
|||
m_pGlobalSection = new CSbieIni("GlobalSettings", this, this);
|
||||
m_pUserSection = new CSbieIni("UserSettings", this, this); // dummy
|
||||
|
||||
m_IniReLoad = false;
|
||||
m_bReloadPending = false;
|
||||
m_bBoxesDirty = false;
|
||||
|
||||
m_LastTraceEntry = 0;
|
||||
|
||||
|
@ -289,7 +291,7 @@ SB_STATUS CSbieAPI::Connect(bool takeOver, bool withQueue)
|
|||
//m->lastRecordNum = 0;
|
||||
|
||||
// Note: this lib is not using all functions hence it can be compatible with multiple driver ABI revisions
|
||||
QStringList CompatVersions = QStringList () << "5.55.0";
|
||||
QStringList CompatVersions = QStringList () << "5.56.0";
|
||||
QString CurVersion = GetVersion();
|
||||
if (!CompatVersions.contains(CurVersion))
|
||||
{
|
||||
|
@ -357,6 +359,7 @@ SB_STATUS CSbieAPI::Disconnect()
|
|||
|
||||
m_SandBoxes.clear();
|
||||
m_BoxedProxesses.clear();
|
||||
m_bBoxesDirty = true;
|
||||
|
||||
emit StatusChanged();
|
||||
return SB_OK;
|
||||
|
@ -786,10 +789,12 @@ SB_STATUS CSbieAPI::TakeOver()
|
|||
return SB_OK;
|
||||
}
|
||||
|
||||
SB_STATUS CSbieAPI::WatchIni(bool bEnable)
|
||||
SB_STATUS CSbieAPI::WatchIni(bool bEnable, bool bReLoad)
|
||||
{
|
||||
if (bEnable)
|
||||
if (bEnable) {
|
||||
m_IniWatcher.addPath(m_IniPath);
|
||||
m_IniReLoad = bReLoad;
|
||||
}
|
||||
else
|
||||
m_IniWatcher.removePath(m_IniPath);
|
||||
return SB_OK;
|
||||
|
@ -807,6 +812,8 @@ void CSbieAPI::OnIniChanged(const QString &path)
|
|||
void CSbieAPI::OnReloadConfig()
|
||||
{
|
||||
m_bReloadPending = false;
|
||||
m_bBoxesDirty = true;
|
||||
if (m_IniReLoad)
|
||||
ReloadConfig();
|
||||
}
|
||||
|
||||
|
@ -1115,13 +1122,17 @@ quint32 CSbieAPI::GetSessionID() const
|
|||
return m->sessionId;
|
||||
}
|
||||
|
||||
SB_STATUS CSbieAPI::ReloadBoxes(bool bFullUpdate)
|
||||
SB_STATUS CSbieAPI::ReloadBoxes(bool bForceUpdate)
|
||||
{
|
||||
if (bForceUpdate || (!m_bBoxesDirty && !m_IniWatcher.files().isEmpty()))
|
||||
return SB_OK;
|
||||
m_bBoxesDirty = false;
|
||||
|
||||
QMap<QString, CSandBoxPtr> OldSandBoxes = m_SandBoxes;
|
||||
|
||||
for (int i = 0;;i++)
|
||||
{
|
||||
QString BoxName = SbieIniGet(QString(), QString(), (i | CONF_GET_NO_EXPAND));
|
||||
QString BoxName = SbieIniGet(QString(), QString(), (i | CONF_GET_NO_EXPAND | CONF_GET_NO_TEMPLS));
|
||||
if (BoxName.isNull())
|
||||
break;
|
||||
|
||||
|
@ -1134,9 +1145,7 @@ SB_STATUS CSbieAPI::ReloadBoxes(bool bFullUpdate)
|
|||
{
|
||||
pBox = CSandBoxPtr(NewSandBox(BoxName, this));
|
||||
m_SandBoxes.insert(BoxName.toLower(), pBox);
|
||||
UpdateBoxPaths(pBox);
|
||||
}
|
||||
else if(bFullUpdate)
|
||||
UpdateBoxPaths(pBox);
|
||||
|
||||
pBox->m_IsEnabled = bIsEnabled;
|
||||
|
@ -1238,6 +1247,8 @@ void CSbieAPI::CommitIniChanges()
|
|||
SbieIniSet("", "", ""); // commit and refresh
|
||||
|
||||
if (bRemoved) m_IniWatcher.addPath(m_IniPath);
|
||||
|
||||
m_bBoxesDirty = true;
|
||||
}
|
||||
|
||||
QString CSbieAPI::SbieIniGetEx(const QString& Section, const QString& Setting)
|
||||
|
@ -1405,6 +1416,12 @@ SB_STATUS CSbieAPI::UpdateProcesses(bool bKeep, bool bAllSessions)
|
|||
if (pBox.isNull())
|
||||
continue;
|
||||
|
||||
if (pBox->m_ActiveProcessCount == 0) {
|
||||
pBox->m_ActiveProcessCount = 1;
|
||||
pBox->OpenBox();
|
||||
emit BoxOpened(pBox->GetName());
|
||||
}
|
||||
|
||||
pProcess->m_pBox = pBox.data();
|
||||
pBox->m_ProcessList.insert(ProcessId, pProcess);
|
||||
m_BoxedProxesses.insert(ProcessId, pProcess);
|
||||
|
@ -1569,9 +1586,11 @@ SB_STATUS CSbieAPI::UpdateBoxPaths(const CSandBoxPtr& pSandBox)
|
|||
if (!Status)
|
||||
return Status;
|
||||
|
||||
pSandBox->m_FilePath = Nt2DosPath(QString::fromWCharArray(FileRoot.c_str(), wcslen(FileRoot.c_str())));
|
||||
pSandBox->m_RegPath = QString::fromWCharArray(KeyRoot.c_str(), wcslen(KeyRoot.c_str()));
|
||||
pSandBox->m_IpcPath = QString::fromWCharArray(IpcRoot.c_str(), wcslen(IpcRoot.c_str()));
|
||||
QString FilePath = Nt2DosPath(QString::fromWCharArray(FileRoot.c_str(), wcslen(FileRoot.c_str())));
|
||||
QString RegPath = QString::fromWCharArray(KeyRoot.c_str(), wcslen(KeyRoot.c_str()));
|
||||
QString IpcPath = QString::fromWCharArray(IpcRoot.c_str(), wcslen(IpcRoot.c_str()));
|
||||
|
||||
pSandBox->SetBoxPaths(FilePath, RegPath, IpcPath);
|
||||
return SB_OK;
|
||||
}
|
||||
|
||||
|
@ -1909,12 +1928,12 @@ QString CSbieAPI::GetBoxedPath(const QString& BoxName, const QString& Path)
|
|||
CSandBoxPtr pBox = GetBoxByName(BoxName);
|
||||
if (!pBox)
|
||||
return QString();
|
||||
return GetBoxedPath(pBox, Path);
|
||||
return GetBoxedPath(pBox.data(), Path);
|
||||
}
|
||||
|
||||
//#pragma comment(lib, "mpr.lib")
|
||||
|
||||
QString CSbieAPI::GetBoxedPath(const CSandBoxPtr& pBox, const QString& Path)
|
||||
QString CSbieAPI::GetBoxedPath(CSandBox* pBox, const QString& Path)
|
||||
{
|
||||
QString BoxRoot = pBox->m_FilePath;
|
||||
|
||||
|
@ -1974,7 +1993,7 @@ QString CSbieAPI::GetBoxedPath(const CSandBoxPtr& pBox, const QString& Path)
|
|||
return Paths;*/
|
||||
}
|
||||
|
||||
QString CSbieAPI::GetRealPath(const CSandBoxPtr& pBox, const QString& Path)
|
||||
QString CSbieAPI::GetRealPath(CSandBox* pBox, const QString& Path)
|
||||
{
|
||||
QString RealPath;
|
||||
QString BoxRoot = pBox->m_FilePath;
|
||||
|
@ -2045,10 +2064,7 @@ SB_STATUS CSbieAPI::ReloadConf(quint32 flags, quint32 SessionId)
|
|||
|
||||
emit ConfigReloaded();
|
||||
|
||||
//emit LogMessage("Sandboxie config has been reloaded.", false);
|
||||
emit LogSbieMessage(0, QStringList() << "Sandboxie config has been reloaded" << "" << "", 4);
|
||||
|
||||
ReloadBoxes(true);
|
||||
m_bBoxesDirty = true;
|
||||
|
||||
return SB_OK;
|
||||
}
|
||||
|
@ -2318,6 +2334,12 @@ CBoxedProcessPtr CSbieAPI::OnProcessBoxed(quint32 ProcessId, const QString& Path
|
|||
if (!pBox)
|
||||
return CBoxedProcessPtr();
|
||||
|
||||
if (pBox->m_ActiveProcessCount == 0) {
|
||||
pBox->m_ActiveProcessCount = 1;
|
||||
pBox->OpenBox();
|
||||
emit BoxOpened(pBox->GetName());
|
||||
}
|
||||
|
||||
pProcess = CBoxedProcessPtr(NewBoxedProcess(ProcessId, pBox.data()));
|
||||
pBox->m_ProcessList.insert(ProcessId, pProcess);
|
||||
m_BoxedProxesses.insert(ProcessId, pProcess);
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
virtual QString GetVersion();
|
||||
|
||||
virtual SB_STATUS TakeOver();
|
||||
virtual SB_STATUS WatchIni(bool bEnable = true);
|
||||
virtual SB_STATUS WatchIni(bool bEnable = true, bool bReLoad = true);
|
||||
|
||||
virtual QString GetSbiePath() const { return m_SbiePath; }
|
||||
virtual QString GetIniPath() const { return m_IniPath; }
|
||||
|
@ -57,7 +57,7 @@ public:
|
|||
virtual void UpdateDriveLetters();
|
||||
virtual QString Nt2DosPath(QString NtPath, bool* pOk = NULL) const;
|
||||
|
||||
virtual SB_STATUS ReloadBoxes(bool bFullUpdate = false);
|
||||
virtual SB_STATUS ReloadBoxes(bool bForceUpdate = false);
|
||||
static SB_STATUS ValidateName(const QString& BoxName);
|
||||
virtual SB_STATUS CreateBox(const QString& BoxName, bool bReLoad = true);
|
||||
|
||||
|
@ -77,8 +77,8 @@ public:
|
|||
virtual bool GetProcessExemption(quint32 process_id, quint32 action_id);
|
||||
|
||||
virtual QString GetBoxedPath(const QString& BoxName, const QString& Path);
|
||||
virtual QString GetBoxedPath(const CSandBoxPtr& pBox, const QString& Path);
|
||||
virtual QString GetRealPath(const CSandBoxPtr& pBox, const QString& Path);
|
||||
virtual QString GetBoxedPath(CSandBox* pBox, const QString& Path);
|
||||
virtual QString GetRealPath(CSandBox* pBox, const QString& Path);
|
||||
|
||||
enum ESetMode
|
||||
{
|
||||
|
@ -158,6 +158,7 @@ signals:
|
|||
void LogSbieMessage(quint32 MsgCode, const QStringList& MsgData, quint32 ProcessId);
|
||||
void ProcessBoxed(quint32 ProcessId, const QString& Path, const QString& Box, quint32 ParentId);
|
||||
void FileToRecover(const QString& BoxName, const QString& FilePath, const QString& BoxPath, quint32 ProcessId);
|
||||
void BoxOpened(const QString& BoxName);
|
||||
void BoxClosed(const QString& BoxName);
|
||||
void NotAuthorized(bool bLoginRequired, bool &bRetry);
|
||||
void QueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 RequestId, const QVariantMap& Data);
|
||||
|
@ -228,8 +229,9 @@ protected:
|
|||
QString m_SbiePath;
|
||||
QString m_IniPath;
|
||||
QFileSystemWatcher m_IniWatcher;
|
||||
|
||||
bool m_IniReLoad;
|
||||
bool m_bReloadPending;
|
||||
bool m_bBoxesDirty;
|
||||
|
||||
bool m_bWithQueue;
|
||||
bool m_bTerminate;
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
#include "stdafx.h"
|
||||
#include "BoxMonitor.h"
|
||||
#include "../MiscHelpers/Common/Common.h"
|
||||
|
||||
CBoxMonitor::CBoxMonitor()
|
||||
{
|
||||
m_bTerminate = false;
|
||||
start();
|
||||
}
|
||||
|
||||
CBoxMonitor::~CBoxMonitor()
|
||||
{
|
||||
m_bTerminate = true;
|
||||
if (!wait(10 * 1000))
|
||||
terminate();
|
||||
}
|
||||
|
||||
void CBoxMonitor::Notify(const wstring& strDirectory)
|
||||
{
|
||||
m_Mutex.lock();
|
||||
m_Boxes[QString::fromStdWString(strDirectory)].Changed = true;
|
||||
m_Mutex.unlock();
|
||||
}
|
||||
|
||||
quint64 CBoxMonitor::CounDirSize(const QString& Directory, SBox* Box)
|
||||
{
|
||||
quint64 TotalSize = 0;
|
||||
if (Box->pBox.isNull() || m_bTerminate)
|
||||
return TotalSize;
|
||||
|
||||
QDir Dir(Directory);
|
||||
foreach(const QFileInfo & Info, Dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot))
|
||||
{
|
||||
if (Info.isDir())
|
||||
TotalSize += CounDirSize(Info.filePath(), Box);
|
||||
else
|
||||
TotalSize += QFile(Info.filePath()).size();
|
||||
}
|
||||
|
||||
return TotalSize;
|
||||
}
|
||||
|
||||
void CBoxMonitor::run()
|
||||
{
|
||||
while (!m_bTerminate)
|
||||
{
|
||||
m_Mutex.lock();
|
||||
QList<QString> Keys = m_Boxes.keys();
|
||||
m_Mutex.unlock();
|
||||
|
||||
quint64 CurTick = GetCurTick();
|
||||
|
||||
foreach(const QString& Key, Keys) {
|
||||
|
||||
m_Mutex.lock();
|
||||
SBox* Box = &m_Boxes[Key];
|
||||
m_Mutex.unlock();
|
||||
|
||||
quint64 MinScanInterval = Box->ScanDuration * 100;
|
||||
if (MinScanInterval < 30 * 1000)
|
||||
MinScanInterval = 30 * 1000;
|
||||
if (MinScanInterval > 30 * 60 * 1000)
|
||||
MinScanInterval = 30 * 60 * 1000;
|
||||
|
||||
if (Box->Changed && (Box->Closed || Box->LastScan == 0 || (CurTick - Box->LastScan) > MinScanInterval)) {
|
||||
|
||||
qDebug() << "Rescanning:" << Key << "(" + QDateTime::currentDateTime().toString() + ")";
|
||||
|
||||
quint64 ScanStart = GetCurTick();
|
||||
|
||||
Box->TotalSize = CounDirSize(Key, Box);
|
||||
|
||||
Box->ScanDuration = GetCurTick() - ScanStart;
|
||||
Box->LastScan = GetCurTick();
|
||||
|
||||
QMetaObject::invokeMethod(this, "UpdateBox", Qt::QueuedConnection,
|
||||
//Q_RETURN_ARG(int, retVal),
|
||||
Q_ARG(QString, Key)
|
||||
);
|
||||
|
||||
Box->Changed = false;
|
||||
}
|
||||
|
||||
m_Mutex.lock();
|
||||
if (Box->pBox.isNull())
|
||||
m_Boxes.remove(Key);
|
||||
m_Mutex.unlock();
|
||||
}
|
||||
|
||||
Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void CBoxMonitor::UpdateBox(const QString& Path)
|
||||
{
|
||||
// Note: this functin runs in the main thread
|
||||
|
||||
m_Mutex.lock();
|
||||
SBox Box = m_Boxes.value(Path);
|
||||
m_Mutex.unlock();
|
||||
|
||||
if (Box.pBox)
|
||||
Box.pBox->SetSize(Box.TotalSize);
|
||||
}
|
||||
|
||||
void CBoxMonitor::AddBox(CSandBoxPlus* pBox, bool AndWatch)
|
||||
{
|
||||
QMutexLocker Lock(&m_Mutex);
|
||||
|
||||
m_Boxes[pBox->GetFileRoot()].pBox = pBox;
|
||||
|
||||
if (AndWatch) {
|
||||
m_Boxes[pBox->GetFileRoot()].Closed = false;
|
||||
AddDirectory(pBox->GetFileRoot().toStdWString().c_str(), true, FILE_NOTIFY_CHANGE_SIZE);
|
||||
}
|
||||
else
|
||||
m_Boxes[pBox->GetFileRoot()].Changed = true;
|
||||
}
|
||||
|
||||
void CBoxMonitor::CloseBox(CSandBoxPlus* pBox, bool AndClear)
|
||||
{
|
||||
QMutexLocker Lock(&m_Mutex);
|
||||
|
||||
if(AndClear)
|
||||
m_Boxes[pBox->GetFileRoot()].pBox.clear();
|
||||
m_Boxes[pBox->GetFileRoot()].Closed = true;
|
||||
|
||||
DetachDirectory(pBox->GetFileRoot().toStdWString().c_str());
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "Helpers/ReadDirectoryChanges.h"
|
||||
#include "SbiePlusAPI.h"
|
||||
|
||||
class CBoxMonitor : public QThread, public CReadDirectoryChanges
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CBoxMonitor();
|
||||
~CBoxMonitor();
|
||||
|
||||
virtual void Notify(const wstring& strDirectory);
|
||||
|
||||
virtual void run();
|
||||
|
||||
void AddBox(CSandBoxPlus* pBox, bool AndWatch = false);
|
||||
void CloseBox(CSandBoxPlus* pBox, bool AndClear = false);
|
||||
|
||||
private slots:
|
||||
void UpdateBox(const QString& Path);
|
||||
|
||||
protected:
|
||||
|
||||
struct SBox
|
||||
{
|
||||
SBox() {
|
||||
Changed = false;
|
||||
Closed = false;
|
||||
LastScan = 0;
|
||||
ScanDuration = 0;
|
||||
TotalSize = 0;
|
||||
}
|
||||
|
||||
QPointer<CSandBoxPlus> pBox;
|
||||
bool Changed;
|
||||
bool Closed;
|
||||
quint64 LastScan;
|
||||
quint64 ScanDuration;
|
||||
|
||||
quint64 TotalSize;
|
||||
};
|
||||
|
||||
quint64 CounDirSize(const QString& Dir, SBox* Box);
|
||||
|
||||
QMutex m_Mutex;
|
||||
QMap<QString, SBox> m_Boxes;
|
||||
bool m_bTerminate;
|
||||
};
|
|
@ -11,7 +11,7 @@
|
|||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
|
|
|
@ -54,6 +54,42 @@
|
|||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="11" column="1">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkNotifications">
|
||||
<property name="text">
|
||||
<string>Show Notifications for relevant log Messages</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="2">
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
|
@ -68,83 +104,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkAsyncBoxOps">
|
||||
<property name="text">
|
||||
<string>Run box operations asynchronously whenever possible (like content deletion)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="uiLang"/>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkShowRecovery">
|
||||
<property name="text">
|
||||
<string>Show first recovery window when emptying sandboxes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkDarkTheme">
|
||||
<property name="text">
|
||||
<string>Use Dark Theme (fully applied after a restart)</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkWatchConfig">
|
||||
<property name="text">
|
||||
<string>Watch Sandboxie.ini for changes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkNotifications">
|
||||
<property name="text">
|
||||
<string>Show Notifications for relevant log Messages</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkNotifyRecovery">
|
||||
<property name="text">
|
||||
<string>Show recoverable files as notifications</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
|
@ -155,6 +114,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkAsyncBoxOps">
|
||||
<property name="text">
|
||||
<string>Run box operations asynchronously whenever possible (like content deletion)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkSandboxUrls">
|
||||
<property name="text">
|
||||
|
@ -165,6 +131,16 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkShowRecovery">
|
||||
<property name="text">
|
||||
<string>Show first recovery window when emptying sandboxes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="uiLang"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="font">
|
||||
|
@ -179,6 +155,37 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkDarkTheme">
|
||||
<property name="text">
|
||||
<string>Use Dark Theme (fully applied after a restart)</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkWatchConfig">
|
||||
<property name="text">
|
||||
<string>Watch Sandboxie.ini for changes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkNotifyRecovery">
|
||||
<property name="text">
|
||||
<string>Show recoverable files as notifications</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkMonitorSize">
|
||||
<property name="text">
|
||||
<string>Count and display the disk space ocupied by each sandbox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright (c) 2010 James E Beveridge
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
// This sample code is for my blog entry titled, "Understanding ReadDirectoryChangesW"
|
||||
// http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw.html
|
||||
// See ReadMe.txt for overview information.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ReadDirectoryChanges.h"
|
||||
#include "ReadDirectoryChangesPrivate.h"
|
||||
|
||||
using namespace ReadDirectoryChangesPrivate;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// CReadDirectoryChanges
|
||||
|
||||
CReadDirectoryChanges::CReadDirectoryChanges()// int nMaxCount) : m_Notifications(nMaxCount)
|
||||
{
|
||||
m_hThread = NULL;
|
||||
m_dwThreadId= 0;
|
||||
m_pServer = new CReadChangesServer(this);
|
||||
}
|
||||
|
||||
CReadDirectoryChanges::~CReadDirectoryChanges()
|
||||
{
|
||||
Terminate();
|
||||
delete m_pServer;
|
||||
}
|
||||
|
||||
void CReadDirectoryChanges::Init()
|
||||
{
|
||||
//
|
||||
// Kick off the worker thread, which will be
|
||||
// managed by CReadChangesServer.
|
||||
//
|
||||
m_hThread = (HANDLE)_beginthreadex(NULL,
|
||||
0,
|
||||
CReadChangesServer::ThreadStartProc,
|
||||
m_pServer,
|
||||
0,
|
||||
&m_dwThreadId
|
||||
);
|
||||
}
|
||||
|
||||
void CReadDirectoryChanges::Terminate()
|
||||
{
|
||||
if (m_hThread)
|
||||
{
|
||||
::QueueUserAPC(CReadChangesServer::TerminateProc, m_hThread, (ULONG_PTR)m_pServer);
|
||||
::WaitForSingleObjectEx(m_hThread, 10000, true);
|
||||
::CloseHandle(m_hThread);
|
||||
|
||||
m_hThread = NULL;
|
||||
m_dwThreadId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CReadDirectoryChanges::AddDirectory( LPCTSTR szDirectory, BOOL bWatchSubtree, DWORD dwNotifyFilter, DWORD dwBufferSize )
|
||||
{
|
||||
if (!m_hThread)
|
||||
Init();
|
||||
|
||||
CReadChangesRequest* pRequest = new CReadChangesRequest(m_pServer, szDirectory, bWatchSubtree, dwNotifyFilter, dwBufferSize);
|
||||
QueueUserAPC(CReadChangesServer::AddDirectoryProc, m_hThread, (ULONG_PTR)pRequest);
|
||||
}
|
||||
|
||||
void CReadDirectoryChanges::DetachDirectory( LPCTSTR szDirectory )
|
||||
{
|
||||
if (!m_hThread)
|
||||
Init();
|
||||
|
||||
pair<ReadDirectoryChangesPrivate::CReadChangesServer*, wstring>* pRequest = new pair<ReadDirectoryChangesPrivate::CReadChangesServer*, wstring>(m_pServer, szDirectory);
|
||||
QueueUserAPC(CReadChangesServer::DetachDirectoryProc, m_hThread, (ULONG_PTR)pRequest);
|
||||
}
|
||||
|
||||
//void CReadDirectoryChanges::Push(DWORD dwAction, wstring& wstrFilename)
|
||||
//{
|
||||
// m_Notifications.push( TDirectoryChangeNotification(dwAction, wstrFilename) );
|
||||
//}
|
||||
//
|
||||
//bool CReadDirectoryChanges::Pop(DWORD& dwAction, wstring& wstrFilename)
|
||||
//{
|
||||
// TDirectoryChangeNotification pair;
|
||||
// if (!m_Notifications.pop(pair))
|
||||
// return false;
|
||||
//
|
||||
// dwAction = pair.first;
|
||||
// wstrFilename = pair.second;
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
//
|
||||
//bool CReadDirectoryChanges::CheckOverflow()
|
||||
//{
|
||||
// bool b = m_Notifications.overflow();
|
||||
// if (b)
|
||||
// m_Notifications.clear();
|
||||
// return b;
|
||||
//}
|
|
@ -0,0 +1,148 @@
|
|||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright (c) 2010 James E Beveridge
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
// This sample code is for my blog entry titled, "Understanding ReadDirectoryChangesW"
|
||||
// http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw.html
|
||||
// See ReadMe.txt for overview information.
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "ThreadSafeQueue.h"
|
||||
|
||||
typedef pair<DWORD,wstring> TDirectoryChangeNotification;
|
||||
|
||||
namespace ReadDirectoryChangesPrivate
|
||||
{
|
||||
class CReadChangesServer;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Track changes to filesystem directories and report them
|
||||
/// to the caller via a thread-safe queue.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This sample code is based on my blog entry titled, "Understanding ReadDirectoryChangesW"
|
||||
/// http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw.html
|
||||
/// </para><para>
|
||||
/// All functions in CReadDirectoryChangesServer run in
|
||||
/// the context of the calling thread.
|
||||
/// </para>
|
||||
/// <example><code>
|
||||
/// CReadDirectoryChanges changes;
|
||||
/// changes.AddDirectory(_T("C:\\"), false, dwNotificationFlags);
|
||||
///
|
||||
/// const HANDLE handles[] = { hStopEvent, changes.GetWaitHandle() };
|
||||
///
|
||||
/// while (!bTerminate)
|
||||
/// {
|
||||
/// ::MsgWaitForMultipleObjectsEx(
|
||||
/// _countof(handles),
|
||||
/// handles,
|
||||
/// INFINITE,
|
||||
/// QS_ALLINPUT,
|
||||
/// MWMO_INPUTAVAILABLE | MWMO_ALERTABLE);
|
||||
/// switch (rc)
|
||||
/// {
|
||||
/// case WAIT_OBJECT_0 + 0:
|
||||
/// bTerminate = true;
|
||||
/// break;
|
||||
/// case WAIT_OBJECT_0 + 1:
|
||||
/// // We've received a notification in the queue.
|
||||
/// {
|
||||
/// DWORD dwAction;
|
||||
/// wstring wstrFilename;
|
||||
/// changes.Pop(dwAction, wstrFilename);
|
||||
/// wprintf(L"%s %s\n", ExplainAction(dwAction), wstrFilename);
|
||||
/// }
|
||||
/// break;
|
||||
/// case WAIT_OBJECT_0 + _countof(handles):
|
||||
/// // Get and dispatch message
|
||||
/// break;
|
||||
/// case WAIT_IO_COMPLETION:
|
||||
/// // APC complete.No action needed.
|
||||
/// break;
|
||||
/// }
|
||||
/// }
|
||||
/// </code></example>
|
||||
/// </remarks>
|
||||
class CReadDirectoryChanges
|
||||
{
|
||||
public:
|
||||
CReadDirectoryChanges();// int nMaxChanges = 1000);
|
||||
~CReadDirectoryChanges();
|
||||
|
||||
void Init();
|
||||
void Terminate();
|
||||
|
||||
/// <summary>
|
||||
/// Add a new directory to be monitored.
|
||||
/// </summary>
|
||||
/// <param name="wszDirectory">Directory to monitor.</param>
|
||||
/// <param name="bWatchSubtree">True to also monitor subdirectories.</param>
|
||||
/// <param name="dwNotifyFilter">The types of file system events to monitor, such as FILE_NOTIFY_CHANGE_ATTRIBUTES.</param>
|
||||
/// <param name="dwBufferSize">The size of the buffer used for overlapped I/O.</param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This function will make an APC call to the worker thread to issue a new
|
||||
/// ReadDirectoryChangesW call for the given directory with the given flags.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
void AddDirectory( LPCTSTR wszDirectory, BOOL bWatchSubtree, DWORD dwNotifyFilter, DWORD dwBufferSize=16384 );
|
||||
|
||||
void DetachDirectory( LPCTSTR wszDirectory );
|
||||
|
||||
virtual void Notify( const wstring& strDirectory ) {}
|
||||
|
||||
/// <summary>
|
||||
/// Return a handle for the Win32 Wait... functions that will be
|
||||
/// signaled when there is a queue entry.
|
||||
/// </summary>
|
||||
//HANDLE GetWaitHandle() { return m_Notifications.GetWaitHandle(); }
|
||||
//
|
||||
//bool Pop(DWORD& dwAction, wstring& wstrFilename);
|
||||
//
|
||||
//// "Push" is for usage by ReadChangesRequest. Not intended for external usage.
|
||||
//void Push(DWORD dwAction, wstring& wstrFilename);
|
||||
//
|
||||
//// Check if the queue overflowed. If so, clear it and return true.
|
||||
//bool CheckOverflow();
|
||||
|
||||
unsigned int GetThreadId() { return m_dwThreadId; }
|
||||
|
||||
protected:
|
||||
ReadDirectoryChangesPrivate::CReadChangesServer* m_pServer;
|
||||
|
||||
HANDLE m_hThread;
|
||||
|
||||
unsigned int m_dwThreadId;
|
||||
|
||||
//CThreadSafeQueue<TDirectoryChangeNotification> m_Notifications;
|
||||
};
|
|
@ -0,0 +1,183 @@
|
|||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright (c) 2010 James E Beveridge
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
// This sample code is for my blog entry titled, "Understanding ReadDirectoryChangesW"
|
||||
// http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw.html
|
||||
// See ReadMe.txt for overview information.
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ReadDirectoryChanges.h"
|
||||
#include "ReadDirectoryChangesPrivate.h"
|
||||
#include <shlwapi.h>
|
||||
|
||||
|
||||
// The namespace is a convenience to emphasize that these are internals
|
||||
// interfaces. The namespace can be safely removed if you need to.
|
||||
namespace ReadDirectoryChangesPrivate
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// CReadChangesRequest
|
||||
|
||||
CReadChangesRequest::CReadChangesRequest(CReadChangesServer* pServer, LPCTSTR sz, BOOL b, DWORD dw, DWORD size)
|
||||
{
|
||||
m_pServer = pServer;
|
||||
m_dwFilterFlags = dw;
|
||||
m_bIncludeChildren = b;
|
||||
m_wstrDirectory = sz;
|
||||
m_hDirectory = 0;
|
||||
|
||||
::ZeroMemory(&m_Overlapped, sizeof(OVERLAPPED));
|
||||
|
||||
// The hEvent member is not used when there is a completion
|
||||
// function, so it's ok to use it to point to the object.
|
||||
m_Overlapped.hEvent = this;
|
||||
|
||||
m_Buffer.resize(size);
|
||||
m_BackupBuffer.resize(size);
|
||||
}
|
||||
|
||||
|
||||
CReadChangesRequest::~CReadChangesRequest()
|
||||
{
|
||||
// RequestTermination() must have been called successfully.
|
||||
_ASSERTE(m_hDirectory == NULL || m_hDirectory == INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
|
||||
bool CReadChangesRequest::OpenDirectory()
|
||||
{
|
||||
// Allow this routine to be called redundantly.
|
||||
if (m_hDirectory)
|
||||
return true;
|
||||
|
||||
m_hDirectory = ::CreateFileW(
|
||||
m_wstrDirectory.c_str(), // pointer to the file name
|
||||
FILE_LIST_DIRECTORY, // access (read/write) mode
|
||||
FILE_SHARE_READ // share mode
|
||||
| FILE_SHARE_WRITE
|
||||
| FILE_SHARE_DELETE,
|
||||
NULL, // security descriptor
|
||||
OPEN_EXISTING, // how to create
|
||||
FILE_FLAG_BACKUP_SEMANTICS // file attributes
|
||||
| FILE_FLAG_OVERLAPPED,
|
||||
NULL); // file with attributes to copy
|
||||
|
||||
if (m_hDirectory == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CReadChangesRequest::BeginRead()
|
||||
{
|
||||
DWORD dwBytes=0;
|
||||
|
||||
// This call needs to be reissued after every APC.
|
||||
BOOL success = ::ReadDirectoryChangesW(
|
||||
m_hDirectory, // handle to directory
|
||||
&m_Buffer[0], // read results buffer
|
||||
m_Buffer.size(), // length of buffer
|
||||
m_bIncludeChildren, // monitoring option
|
||||
m_dwFilterFlags, // filter conditions
|
||||
&dwBytes, // bytes returned
|
||||
&m_Overlapped, // overlapped buffer
|
||||
&NotificationCompletion); // completion routine
|
||||
}
|
||||
|
||||
//static
|
||||
VOID CALLBACK CReadChangesRequest::NotificationCompletion(
|
||||
DWORD dwErrorCode, // completion code
|
||||
DWORD dwNumberOfBytesTransfered, // number of bytes transferred
|
||||
LPOVERLAPPED lpOverlapped) // I/O information buffer
|
||||
{
|
||||
CReadChangesRequest* pBlock = (CReadChangesRequest*)lpOverlapped->hEvent;
|
||||
|
||||
if (dwErrorCode == ERROR_OPERATION_ABORTED)
|
||||
{
|
||||
::InterlockedDecrement(&pBlock->m_pServer->m_nOutstandingRequests);
|
||||
delete pBlock;
|
||||
return;
|
||||
}
|
||||
|
||||
// This might mean overflow? Not sure.
|
||||
if(!dwNumberOfBytesTransfered)
|
||||
return;
|
||||
|
||||
// Can't use sizeof(FILE_NOTIFY_INFORMATION) because
|
||||
// the structure is padded to 16 bytes.
|
||||
_ASSERTE(dwNumberOfBytesTransfered >= offsetof(FILE_NOTIFY_INFORMATION, FileName) + sizeof(WCHAR));
|
||||
|
||||
pBlock->BackupBuffer(dwNumberOfBytesTransfered);
|
||||
|
||||
// Get the new read issued as fast as possible. The documentation
|
||||
// says that the original OVERLAPPED structure will not be used
|
||||
// again once the completion routine is called.
|
||||
pBlock->BeginRead();
|
||||
|
||||
//pBlock->ProcessNotification();
|
||||
|
||||
pBlock->m_pServer->m_pBase->Notify(pBlock->GetDirectory());
|
||||
}
|
||||
|
||||
void CReadChangesRequest::ProcessNotification()
|
||||
{
|
||||
BYTE* pBase = m_BackupBuffer.data();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
FILE_NOTIFY_INFORMATION& fni = (FILE_NOTIFY_INFORMATION&)*pBase;
|
||||
|
||||
wstring wstrFilename(fni.FileName, fni.FileNameLength/sizeof(wchar_t));
|
||||
// Handle a trailing backslash, such as for a root directory.
|
||||
if (m_wstrDirectory.back() != L'\\')
|
||||
wstrFilename = m_wstrDirectory + L"\\" + wstrFilename;
|
||||
else
|
||||
wstrFilename = m_wstrDirectory + wstrFilename;
|
||||
|
||||
// If it could be a short filename, expand it.
|
||||
LPCWSTR wszFilename = PathFindFileNameW(wstrFilename.c_str());
|
||||
int len = lstrlenW(wszFilename);
|
||||
// The maximum length of an 8.3 filename is twelve, including the dot.
|
||||
if (len <= 12 && wcschr(wszFilename, L'~'))
|
||||
{
|
||||
// Convert to the long filename form. Unfortunately, this
|
||||
// does not work for deletions, so it's an imperfect fix.
|
||||
wchar_t wbuf[MAX_PATH];
|
||||
if (::GetLongPathNameW(wstrFilename.c_str(), wbuf, _countof(wbuf)) > 0)
|
||||
wstrFilename = wbuf;
|
||||
}
|
||||
|
||||
//m_pServer->m_pBase->Push(fni.Action, wstrFilename);
|
||||
|
||||
if (!fni.NextEntryOffset)
|
||||
break;
|
||||
pBase += fni.NextEntryOffset;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright (c) 2010 James E Beveridge
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
// This sample code is for my blog entry titled, "Understanding ReadDirectoryChangesW"
|
||||
// http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw.html
|
||||
// See ReadMe.txt for overview information.
|
||||
|
||||
class CReadDirectoryChanges;
|
||||
|
||||
namespace ReadDirectoryChangesPrivate
|
||||
{
|
||||
|
||||
class CReadChangesServer;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// All functions in CReadChangesRequest run in the context of the worker thread.
|
||||
// One instance of this object is created for each call to AddDirectory().
|
||||
class CReadChangesRequest
|
||||
{
|
||||
public:
|
||||
CReadChangesRequest(CReadChangesServer* pServer, LPCTSTR sz, BOOL b, DWORD dw, DWORD size);
|
||||
|
||||
~CReadChangesRequest();
|
||||
|
||||
bool OpenDirectory();
|
||||
|
||||
void BeginRead();
|
||||
|
||||
// The dwSize is the actual number of bytes sent to the APC.
|
||||
void BackupBuffer(DWORD dwSize)
|
||||
{
|
||||
// We could just swap back and forth between the two
|
||||
// buffers, but this code is easier to understand and debug.
|
||||
memcpy(&m_BackupBuffer[0], &m_Buffer[0], dwSize);
|
||||
}
|
||||
|
||||
void ProcessNotification();
|
||||
|
||||
void RequestTermination()
|
||||
{
|
||||
// ::CancelIoEx(m_hDirectory, &m_Overlapped);
|
||||
::CancelIo(m_hDirectory);
|
||||
::CloseHandle(m_hDirectory);
|
||||
m_hDirectory = nullptr;
|
||||
}
|
||||
|
||||
const wstring& GetDirectory() { return m_wstrDirectory; }
|
||||
|
||||
CReadChangesServer* m_pServer;
|
||||
|
||||
protected:
|
||||
|
||||
static VOID CALLBACK NotificationCompletion(
|
||||
DWORD dwErrorCode, // completion code
|
||||
DWORD dwNumberOfBytesTransfered, // number of bytes transferred
|
||||
LPOVERLAPPED lpOverlapped); // I/O information buffer
|
||||
|
||||
// Parameters from the caller for ReadDirectoryChangesW().
|
||||
DWORD m_dwFilterFlags;
|
||||
BOOL m_bIncludeChildren;
|
||||
wstring m_wstrDirectory;
|
||||
|
||||
// Result of calling CreateFile().
|
||||
HANDLE m_hDirectory;
|
||||
|
||||
// Required parameter for ReadDirectoryChangesW().
|
||||
OVERLAPPED m_Overlapped;
|
||||
|
||||
// Data buffer for the request.
|
||||
// Since the memory is allocated by malloc, it will always
|
||||
// be aligned as required by ReadDirectoryChangesW().
|
||||
vector<BYTE> m_Buffer;
|
||||
|
||||
// Double buffer strategy so that we can issue a new read
|
||||
// request before we process the current buffer.
|
||||
vector<BYTE> m_BackupBuffer;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// All functions in CReadChangesServer run in the context of the worker thread.
|
||||
// One instance of this object is allocated for each instance of CReadDirectoryChanges.
|
||||
// This class is responsible for thread startup, orderly thread shutdown, and shimming
|
||||
// the various C++ member functions with C-style Win32 functions.
|
||||
class CReadChangesServer
|
||||
{
|
||||
public:
|
||||
CReadChangesServer(CReadDirectoryChanges* pParent)
|
||||
{
|
||||
m_bTerminate=false; m_nOutstandingRequests=0;m_pBase=pParent;
|
||||
}
|
||||
|
||||
static unsigned int WINAPI ThreadStartProc(LPVOID arg)
|
||||
{
|
||||
CReadChangesServer* pServer = (CReadChangesServer*)arg;
|
||||
pServer->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Called by QueueUserAPC to start orderly shutdown.
|
||||
static void CALLBACK TerminateProc(__in ULONG_PTR arg)
|
||||
{
|
||||
CReadChangesServer* pServer = (CReadChangesServer*)arg;
|
||||
pServer->RequestTermination();
|
||||
}
|
||||
|
||||
// Called by QueueUserAPC to add another directory.
|
||||
static void CALLBACK AddDirectoryProc(__in ULONG_PTR arg)
|
||||
{
|
||||
CReadChangesRequest* pRequest = (CReadChangesRequest*)arg;
|
||||
pRequest->m_pServer->AddDirectory(pRequest);
|
||||
}
|
||||
|
||||
static void CALLBACK DetachDirectoryProc(__in ULONG_PTR arg)
|
||||
{
|
||||
pair<ReadDirectoryChangesPrivate::CReadChangesServer*, wstring>* pRequest = (pair<ReadDirectoryChangesPrivate::CReadChangesServer*, wstring>*)arg;
|
||||
pRequest->first->DetachDirectory(pRequest);
|
||||
}
|
||||
|
||||
CReadDirectoryChanges* m_pBase;
|
||||
|
||||
volatile DWORD m_nOutstandingRequests;
|
||||
|
||||
protected:
|
||||
|
||||
void Run()
|
||||
{
|
||||
while (m_nOutstandingRequests || !m_bTerminate)
|
||||
{
|
||||
DWORD rc = ::SleepEx(INFINITE, true);
|
||||
}
|
||||
}
|
||||
|
||||
void AddDirectory( CReadChangesRequest* pBlock )
|
||||
{
|
||||
for (auto I = m_pBlocks.begin(); I != m_pBlocks.end(); ++I)
|
||||
{
|
||||
if ((*I)->GetDirectory() == pBlock->GetDirectory())
|
||||
{
|
||||
delete pBlock;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pBlock->OpenDirectory())
|
||||
{
|
||||
::InterlockedIncrement(&pBlock->m_pServer->m_nOutstandingRequests);
|
||||
m_pBlocks.push_back(pBlock);
|
||||
pBlock->BeginRead();
|
||||
}
|
||||
else
|
||||
delete pBlock;
|
||||
}
|
||||
|
||||
void DetachDirectory(pair<ReadDirectoryChangesPrivate::CReadChangesServer*, wstring>* pRequest)
|
||||
{
|
||||
for (auto I = m_pBlocks.begin(); I != m_pBlocks.end(); )
|
||||
{
|
||||
if ((*I)->GetDirectory() == pRequest->second)
|
||||
{
|
||||
::InterlockedDecrement(&pRequest->first->m_nOutstandingRequests);
|
||||
(*I)->RequestTermination();
|
||||
delete (*I);
|
||||
I = m_pBlocks.erase(I);
|
||||
}
|
||||
else
|
||||
++I;
|
||||
}
|
||||
delete pRequest;
|
||||
}
|
||||
|
||||
void RequestTermination()
|
||||
{
|
||||
m_bTerminate = true;
|
||||
|
||||
for (DWORD i=0; i<m_pBlocks.size(); ++i)
|
||||
{
|
||||
// Each Request object will delete itself.
|
||||
m_pBlocks[i]->RequestTermination();
|
||||
}
|
||||
|
||||
m_pBlocks.clear();
|
||||
}
|
||||
|
||||
vector<CReadChangesRequest*> m_pBlocks;
|
||||
|
||||
bool m_bTerminate;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright (c) 2010 James E Beveridge
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
// This sample code is for my blog entry titled, "Understanding ReadDirectoryChangesW"
|
||||
// http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw.html
|
||||
// See ReadMe.txt for overview information.
|
||||
|
||||
#include <list>
|
||||
|
||||
template <typename C>
|
||||
class CThreadSafeQueue : protected std::list<C>
|
||||
{
|
||||
public:
|
||||
CThreadSafeQueue(int nMaxCount)
|
||||
{
|
||||
m_bOverflow = false;
|
||||
|
||||
m_hSemaphore = ::CreateSemaphore(
|
||||
NULL, // no security attributes
|
||||
0, // initial count
|
||||
nMaxCount, // max count
|
||||
NULL); // anonymous
|
||||
}
|
||||
|
||||
~CThreadSafeQueue()
|
||||
{
|
||||
::CloseHandle(m_hSemaphore);
|
||||
m_hSemaphore = NULL;
|
||||
}
|
||||
|
||||
void push(C& c)
|
||||
{
|
||||
//CComCritSecLock<CComAutoCriticalSection> lock( m_Crit, true );
|
||||
QMutexLocker lock(&m_Mutex);
|
||||
push_back( c );
|
||||
//lock.Unlock();
|
||||
lock.unlock();
|
||||
|
||||
if (!::ReleaseSemaphore(m_hSemaphore, 1, NULL))
|
||||
{
|
||||
// If the semaphore is full, then take back the entry.
|
||||
//lock.Lock();
|
||||
lock.relock();
|
||||
pop_back();
|
||||
if (GetLastError() == ERROR_TOO_MANY_POSTS)
|
||||
{
|
||||
m_bOverflow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool pop(C& c)
|
||||
{
|
||||
//CComCritSecLock<CComAutoCriticalSection> lock( m_Crit, true );
|
||||
QMutexLocker lock(&m_Mutex);
|
||||
|
||||
// If the user calls pop() more than once after the
|
||||
// semaphore is signaled, then the semaphore count will
|
||||
// get out of sync. We fix that when the queue empties.
|
||||
if (empty())
|
||||
{
|
||||
while (::WaitForSingleObject(m_hSemaphore, 0) != WAIT_TIMEOUT)
|
||||
1;
|
||||
return false;
|
||||
}
|
||||
|
||||
c = front();
|
||||
pop_front();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If overflow, use this to clear the queue.
|
||||
void clear()
|
||||
{
|
||||
//CComCritSecLock<CComAutoCriticalSection> lock( m_Crit, true );
|
||||
QMutexLocker lock(&m_Mutex);
|
||||
|
||||
for (DWORD i=0; i<size(); i++)
|
||||
WaitForSingleObject(m_hSemaphore, 0);
|
||||
|
||||
__super::clear();
|
||||
|
||||
m_bOverflow = false;
|
||||
}
|
||||
|
||||
bool overflow()
|
||||
{
|
||||
return m_bOverflow;
|
||||
}
|
||||
|
||||
HANDLE GetWaitHandle() { return m_hSemaphore; }
|
||||
|
||||
protected:
|
||||
HANDLE m_hSemaphore;
|
||||
|
||||
//CComAutoCriticalSection m_Crit;
|
||||
QMutex m_Mutex;
|
||||
|
||||
bool m_bOverflow;
|
||||
};
|
|
@ -71,8 +71,8 @@ QList<QVariant> CMonitorModel::Sync(const QMap<QString, CMonitorEntryPtr>& Entry
|
|||
|
||||
/*switch (section)
|
||||
{
|
||||
//case eType: ColValue.Formated = ; break;
|
||||
//case eValue: ColValue.Formated = ; break;
|
||||
//case eType: ColValue.Formatted = ; break;
|
||||
//case eValue: ColValue.Formatted = ; break;
|
||||
}*/
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include "SbieModel.h"
|
||||
#include "../../MiscHelpers/Common/Common.h"
|
||||
#include "../../MiscHelpers/Common/IconExtreactor.h"
|
||||
#include <QFileIconProvider>
|
||||
#include "../SandMan.h"
|
||||
|
||||
CSbieModel::CSbieModel(QObject *parent)
|
||||
|
@ -114,6 +113,8 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList, cons
|
|||
QMap<QList<QVariant>, QList<STreeNode*> > New;
|
||||
QHash<QVariant, STreeNode*> Old = m_Map;
|
||||
|
||||
bool bWatchSize = theConf->GetBool("Options/WatchBoxSize", false);
|
||||
|
||||
foreach(const QString& Group, Groups.keys())
|
||||
{
|
||||
if (Group.isEmpty())
|
||||
|
@ -232,6 +233,7 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList, cons
|
|||
{
|
||||
case eName: Value = pBox->GetName(); break;
|
||||
case eStatus: Value = pBox.objectCast<CSandBoxPlus>()->GetStatusStr(); break;
|
||||
case eInfo: Value = bWatchSize ? pBox.objectCast<CSandBoxPlus>()->GetSize() : 0; break;
|
||||
case ePath: Value = pBox->GetFileRoot(); break;
|
||||
}
|
||||
|
||||
|
@ -245,7 +247,8 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList, cons
|
|||
|
||||
switch (section)
|
||||
{
|
||||
case eName: ColValue.Formated = Value.toString().replace("_", " "); break;
|
||||
case eName: ColValue.Formatted = Value.toString().replace("_", " "); break;
|
||||
case eInfo: ColValue.Formatted = Value.toULongLong() > 0 ? FormatSize(Value.toULongLong()) : ""; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,8 +276,6 @@ bool CSbieModel::Sync(const CSandBoxPtr& pBox, const QList<QVariant>& Path, cons
|
|||
|
||||
int ActiveCount = 0;
|
||||
|
||||
QFileIconProvider IconProvider;
|
||||
|
||||
foreach(const CBoxedProcessPtr& pProc, ProcessList)
|
||||
{
|
||||
QSharedPointer<CSbieProcess> pProcess = pProc.objectCast<CSbieProcess>();
|
||||
|
@ -326,7 +327,7 @@ bool CSbieModel::Sync(const CSandBoxPtr& pBox, const QList<QVariant>& Path, cons
|
|||
//else
|
||||
// pNode->Icon = icons.first().pixmap;
|
||||
|
||||
pNode->Icon = IconProvider.icon(QFileInfo(pProcess->GetFileName()));
|
||||
pNode->Icon = m_IconProvider.icon(QFileInfo(pProcess->GetFileName()));
|
||||
if (pNode->Icon.isNull() || !pNode->Icon.isValid())
|
||||
pNode->Icon = m_ExeIcon;
|
||||
Changed = 1;
|
||||
|
@ -345,7 +346,7 @@ bool CSbieModel::Sync(const CSandBoxPtr& pBox, const QList<QVariant>& Path, cons
|
|||
case eStatus: Value = pProcess->GetStatusStr(); break;
|
||||
case eTitle: Value = theAPI->GetProcessTitle(pProcess->GetProcessId()); break;
|
||||
//case eLogCount: break; // todo Value = pProcess->GetResourceLog().count(); break;
|
||||
case eTimeStamp: Value = pProcess->GetTimeStamp(); break;
|
||||
case eInfo: Value = pProcess->GetTimeStamp(); break;
|
||||
//case ePath: Value = pProcess->GetFileName(); break;
|
||||
case ePath: {
|
||||
QString CmdLine = pProcess->GetCommandLine();
|
||||
|
@ -364,9 +365,9 @@ bool CSbieModel::Sync(const CSandBoxPtr& pBox, const QList<QVariant>& Path, cons
|
|||
|
||||
switch (section)
|
||||
{
|
||||
case eProcessId: ColValue.Formated = QString::number(pProcess->GetProcessId()); break;
|
||||
//case eLogCount: ColValue.Formated = QString::number(Value.toInt()); break;
|
||||
case eTimeStamp: ColValue.Formated = pProcess->GetTimeStamp().toString("hh:mm:ss"); break;
|
||||
case eProcessId: ColValue.Formatted = QString::number(pProcess->GetProcessId()); break;
|
||||
//case eLogCount: ColValue.Formatted = QString::number(Value.toInt()); break;
|
||||
case eInfo: ColValue.Formatted = pProcess->GetTimeStamp().toString("hh:mm:ss"); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,8 +476,10 @@ QVariant CSbieModel::headerData(int section, Qt::Orientation orientation, int ro
|
|||
case eProcessId: return tr("Process ID");
|
||||
case eStatus: return tr("Status");
|
||||
case eTitle: return tr("Title");
|
||||
case eInfo: return tr("Info");
|
||||
//case eSize: return tr("Size");
|
||||
//case eLogCount: return tr("Log Count");
|
||||
case eTimeStamp: return tr("Start Time");
|
||||
//case eTimeStamp: return tr("Start Time");
|
||||
case ePath: return tr("Path / Command Line");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "../SbieProcess.h"
|
||||
#include "../../MiscHelpers/Common/TreeItemModel.h"
|
||||
#include <QMimeData>
|
||||
|
||||
#include <QFileIconProvider>
|
||||
|
||||
class CSbieModel : public CTreeItemModel
|
||||
{
|
||||
|
@ -45,8 +45,10 @@ public:
|
|||
eProcessId,
|
||||
eTitle,
|
||||
eStatus,
|
||||
eInfo,
|
||||
//eSize,
|
||||
//eLogCount,
|
||||
eTimeStamp,
|
||||
//eTimeStamp,
|
||||
ePath,
|
||||
eCount
|
||||
};
|
||||
|
@ -92,4 +94,5 @@ private:
|
|||
QIcon m_ExeIcon;
|
||||
|
||||
QString m_SbieModelMimeType;
|
||||
QFileIconProvider m_IconProvider;
|
||||
};
|
|
@ -155,20 +155,20 @@ QList<QVariant> CTraceModel::Sync(const QVector<CTraceEntryPtr>& EntryList, int
|
|||
/*case eProcess:
|
||||
{
|
||||
CBoxedProcessPtr pProcess = theAPI->GetProcessById(pEntry->GetProcessId());
|
||||
ColValue.Formated = QString("%1 (%2, %3)").arg(pProcess.isNull() ? tr("Unknown") : pProcess->GetProcessName()).arg(pEntry->GetProcessId()).arg(pEntry->GetThreadId());
|
||||
ColValue.Formatted = QString("%1 (%2, %3)").arg(pProcess.isNull() ? tr("Unknown") : pProcess->GetProcessName()).arg(pEntry->GetProcessId()).arg(pEntry->GetThreadId());
|
||||
break;
|
||||
}
|
||||
case eTimeStamp: ColValue.Formated = pEntry->GetTimeStamp().toString("hh:mm:ss.zzz"); break;*/
|
||||
case eTimeStamp: ColValue.Formatted = pEntry->GetTimeStamp().toString("hh:mm:ss.zzz"); break;*/
|
||||
case eProcess:
|
||||
if(!m_bTree) {
|
||||
QString Name = pEntry->GetProcessName();
|
||||
ColValue.Formated = QString("%1 (%2, %3) - %4").arg(Name.isEmpty() ? tr("Unknown") : Name)
|
||||
ColValue.Formatted = QString("%1 (%2, %3) - %4").arg(Name.isEmpty() ? tr("Unknown") : Name)
|
||||
.arg(pEntry->GetProcessId()).arg(pEntry->GetThreadId()).arg(pEntry->GetTimeStamp().toString("hh:mm:ss.zzz"));
|
||||
} else
|
||||
ColValue.Formated = pEntry->GetTimeStamp().toString("hh:mm:ss.zzz");
|
||||
ColValue.Formatted = pEntry->GetTimeStamp().toString("hh:mm:ss.zzz");
|
||||
break;
|
||||
//case eType: ColValue.Formated = ; break;
|
||||
//case eValue: ColValue.Formated = ; break;
|
||||
//case eType: ColValue.Formatted = ; break;
|
||||
//case eValue: ColValue.Formatted = ; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,9 +252,9 @@ CTraceModel::STreeNode* CTraceModel::MkVirtualNode(const QVariant& Id, STreeNode
|
|||
QString Name = GetProcessName(pid);
|
||||
pNode->Values[0].Raw = pid;
|
||||
if(!Name.isEmpty())
|
||||
pNode->Values[0].Formated = tr("%1 (%2)").arg(Name).arg(pid);
|
||||
pNode->Values[0].Formatted = tr("%1 (%2)").arg(Name).arg(pid);
|
||||
else
|
||||
pNode->Values[0].Formated = tr("Process %1").arg(pid);
|
||||
pNode->Values[0].Formatted = tr("Process %1").arg(pid);
|
||||
}
|
||||
else if (typeId.first == "tid")
|
||||
{
|
||||
|
@ -262,10 +262,10 @@ CTraceModel::STreeNode* CTraceModel::MkVirtualNode(const QVariant& Id, STreeNode
|
|||
quint32 pid = Split2(pParent->ID.toString(), "_").second.toUInt();
|
||||
LogThreadId(pid, tid);
|
||||
pNode->Values[0].Raw = tid;
|
||||
pNode->Values[0].Formated = tr("Thread %1").arg(tid);
|
||||
pNode->Values[0].Formatted = tr("Thread %1").arg(tid);
|
||||
}
|
||||
else*/
|
||||
pNode->Values[0].Raw = pNode->Values[0].Formated = Id;
|
||||
pNode->Values[0].Raw = pNode->Values[0].Formatted = Id;
|
||||
|
||||
return pNode;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
<file>IconOffC.png</file>
|
||||
<file>IconOffCx.png</file>
|
||||
<file>Actions/Monitor.png</file>
|
||||
<file>SideLogo.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/Boxes">
|
||||
<file alias="Empty3">Boxes/sandbox-b-empty.png</file>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -21,6 +21,7 @@
|
|||
#include "Views/TraceView.h"
|
||||
#include "Windows/SelectBoxWindow.h"
|
||||
#include "../UGlobalHotkey/uglobalhotkeys.h"
|
||||
#include "Wizards/SetupWizard.h"
|
||||
#include "Helpers/WinAdmin.h"
|
||||
|
||||
CSbiePlusAPI* theAPI = NULL;
|
||||
|
@ -203,25 +204,6 @@ CSandMan::CSandMan(QWidget *parent)
|
|||
|
||||
CreateTrayMenu();
|
||||
|
||||
/*QWidgetAction* pBoxWidget = new QWidgetAction(m_pTrayMenu);
|
||||
|
||||
QWidget* pWidget = new QWidget();
|
||||
pWidget->setMaximumHeight(200);
|
||||
QGridLayout* pLayout = new QGridLayout();
|
||||
pLayout->addWidget(pBar, 0, 0);
|
||||
pWidget->setLayout(pLayout);
|
||||
pBoxWidget->setDefaultWidget(pWidget);*/
|
||||
|
||||
/*QLabel* pLabel = new QLabel("test");
|
||||
pLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
pLabel->setAlignment(Qt::AlignCenter);
|
||||
pBoxWidget->setDefaultWidget(pLabel);*/
|
||||
|
||||
//m_pTrayMenu->addAction(pBoxWidget);
|
||||
//m_pTrayMenu->addSeparator();
|
||||
|
||||
m_pTrayMenu->addAction(m_pExit);
|
||||
|
||||
bool bAutoRun = QApplication::arguments().contains("-autorun");
|
||||
|
||||
if(g_PendingMessage.isEmpty()){
|
||||
|
@ -355,6 +337,7 @@ void CSandMan::CreateMenus()
|
|||
m_pStopSvc = m_pMaintenanceItems->addAction(tr("Stop Service"), this, SLOT(OnMaintenance()));
|
||||
m_pUninstallSvc = m_pMaintenanceItems->addAction(tr("Uninstall Service"), this, SLOT(OnMaintenance()));
|
||||
m_pMaintenance->addSeparator();
|
||||
m_pSetupWizard = m_pMaintenance->addAction(CSandMan::GetIcon("Software"), tr("Setup Wizard"), this, SLOT(OnMaintenance()));
|
||||
if(IsFullyPortable())
|
||||
m_pUninstallAll = m_pMaintenance->addAction(CSandMan::GetIcon("Uninstall"), tr("Uninstall All"), this, SLOT(OnMaintenance()));
|
||||
|
||||
|
@ -384,6 +367,8 @@ void CSandMan::CreateMenus()
|
|||
|
||||
m_pMenuView->addSeparator();
|
||||
|
||||
m_pRefreshAll = m_pMenuView->addAction(CSandMan::GetIcon("Recover"), tr("Refresh View"), this, SLOT(OnRefresh()));
|
||||
|
||||
m_pCleanUpMenu = m_pMenuView->addMenu(CSandMan::GetIcon("Clean"), tr("Clean Up"));
|
||||
m_pCleanUpProcesses = m_pCleanUpMenu->addAction(tr("Cleanup Processes"), this, SLOT(OnCleanUp()));
|
||||
m_pCleanUpMenu->addSeparator();
|
||||
|
@ -594,6 +579,25 @@ void CSandMan::CreateTrayMenu()
|
|||
m_pDisableForce2 = m_pTrayMenu->addAction(tr("Pause Forcing Programs"), this, SLOT(OnDisableForce2()));
|
||||
m_pDisableForce2->setCheckable(true);
|
||||
m_pTrayMenu->addSeparator();
|
||||
|
||||
/*QWidgetAction* pBoxWidget = new QWidgetAction(m_pTrayMenu);
|
||||
|
||||
QWidget* pWidget = new QWidget();
|
||||
pWidget->setMaximumHeight(200);
|
||||
QGridLayout* pLayout = new QGridLayout();
|
||||
pLayout->addWidget(pBar, 0, 0);
|
||||
pWidget->setLayout(pLayout);
|
||||
pBoxWidget->setDefaultWidget(pWidget);*/
|
||||
|
||||
/*QLabel* pLabel = new QLabel("test");
|
||||
pLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
pLabel->setAlignment(Qt::AlignCenter);
|
||||
pBoxWidget->setDefaultWidget(pLabel);*/
|
||||
|
||||
//m_pTrayMenu->addAction(pBoxWidget);
|
||||
//m_pTrayMenu->addSeparator();
|
||||
|
||||
m_pTrayMenu->addAction(m_pExit);
|
||||
}
|
||||
|
||||
void CSandMan::OnExit()
|
||||
|
@ -1027,8 +1031,10 @@ SB_STATUS CSandMan::DeleteBoxContent(const CSandBoxPtr& pBox, EDelMode Mode, boo
|
|||
Status = pBox->CleanBox();
|
||||
|
||||
Ret = Status;
|
||||
if (Status.GetStatus() == OP_ASYNC)
|
||||
if (Status.GetStatus() == OP_ASYNC) {
|
||||
Ret = AddAsyncOp(Status.GetValue(), true, tr("Auto Deleting %1 Content").arg(pBox->GetName()));
|
||||
pBox.objectCast<CSandBoxPlus>()->UpdateSize();
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
|
@ -1142,8 +1148,7 @@ void CSandMan::OnStatusChanged()
|
|||
|
||||
OnIniReloaded();
|
||||
|
||||
if (theConf->GetBool("Options/WatchIni", true))
|
||||
theAPI->WatchIni(true);
|
||||
theAPI->WatchIni(true, theConf->GetBool("Options/WatchIni", true));
|
||||
|
||||
if (!theAPI->ReloadCert().IsError()) {
|
||||
CSettingsWindow::LoadCertificate();
|
||||
|
@ -1173,6 +1178,18 @@ void CSandMan::OnStatusChanged()
|
|||
OnLogMessage(tr("Default sandbox not found; creating: %1").arg("DefaultBox"));
|
||||
theAPI->CreateBox("DefaultBox");
|
||||
}
|
||||
|
||||
int BusinessUse = theConf->GetInt("Options/BusinessUse", 2);
|
||||
if (g_CertInfo.business && BusinessUse == 0) // if we have a Business cert switch to that use case
|
||||
theConf->SetValue("Options/BusinessUse", 1);
|
||||
|
||||
int WizardLevel = theConf->GetBool("Options/WizardLevel", 0);
|
||||
if (WizardLevel == 0) {
|
||||
if (CSetupWizard::ShowWizard())
|
||||
UpdateSettings();
|
||||
else // if user canceled mark that and not show again
|
||||
theConf->SetValue("Options/WizardLevel", -1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1727,6 +1744,12 @@ void CSandMan::OnMaintenance()
|
|||
CSbieUtils::RemoveContextMenu2();
|
||||
}
|
||||
|
||||
else if (sender() == m_pSetupWizard) {
|
||||
if (CSetupWizard::ShowWizard())
|
||||
UpdateSettings();
|
||||
return;
|
||||
}
|
||||
|
||||
HandleMaintenance(Status);
|
||||
}
|
||||
|
||||
|
@ -1838,6 +1861,20 @@ void CSandMan::SetViewMode(bool bAdvanced)
|
|||
}
|
||||
}
|
||||
|
||||
void CSandMan::OnRefresh()
|
||||
{
|
||||
if (!theAPI->IsConnected())
|
||||
return;
|
||||
|
||||
theAPI->ReloadBoxes(true);
|
||||
|
||||
if (theConf->GetBool("Options/WatchBoxSize", false)) {
|
||||
QMap<QString, CSandBoxPtr> Boxes = theAPI->GetAllBoxes();
|
||||
foreach(const CSandBoxPtr & pBox, Boxes)
|
||||
pBox.objectCast<CSandBoxPlus>()->UpdateSize();
|
||||
}
|
||||
}
|
||||
|
||||
void CSandMan::OnCleanUp()
|
||||
{
|
||||
if (sender() == m_pCleanUpMsgLog || sender() == m_pCleanUpButton)
|
||||
|
@ -2031,6 +2068,8 @@ void CSandMan::OnReloadIni()
|
|||
|
||||
void CSandMan::OnIniReloaded()
|
||||
{
|
||||
OnLogSbieMessage(0, QStringList() << "Sandboxie config has been reloaded" << "" << "", 4);
|
||||
|
||||
m_pBoxView->ReloadUserConfig();
|
||||
m_pPopUpWindow->ReloadHiddenMessages();
|
||||
}
|
||||
|
|
|
@ -179,6 +179,7 @@ private slots:
|
|||
|
||||
void OnViewMode(QAction* action);
|
||||
void OnAlwaysTop();
|
||||
void OnRefresh();
|
||||
void OnCleanUp();
|
||||
void OnProcView();
|
||||
|
||||
|
@ -258,6 +259,7 @@ private:
|
|||
QAction* m_pUninstallSvc;
|
||||
QAction* m_pStopAll;
|
||||
QAction* m_pUninstallAll;
|
||||
QAction* m_pSetupWizard;
|
||||
QAction* m_pExit;
|
||||
|
||||
QMenu* m_pMenuView;
|
||||
|
@ -265,6 +267,7 @@ private:
|
|||
QAction* m_pShowHidden;
|
||||
QAction* m_pWndTopMost;
|
||||
int m_iMenuViewPos;
|
||||
QAction* m_pRefreshAll;
|
||||
QMenu* m_pCleanUpMenu;
|
||||
QAction* m_pCleanUpProcesses;
|
||||
QAction* m_pCleanUpMsgLog;
|
||||
|
|
|
@ -8,6 +8,7 @@ HEADERS += ./stdafx.h \
|
|||
./SbiePlusAPI.h \
|
||||
./SbieProcess.h \
|
||||
./BoxJob.h \
|
||||
./BoxMonitor.h \
|
||||
./Models/SbieModel.h \
|
||||
./Models/TraceModel.h \
|
||||
./Models/MonitorModel.h \
|
||||
|
@ -16,6 +17,8 @@ HEADERS += ./stdafx.h \
|
|||
./Dialogs/MultiErrorDialog.h \
|
||||
./Helpers/FindTool.h \
|
||||
./Helpers/WinAdmin.h \
|
||||
./Helpers/ReadDirectoryChanges.h \
|
||||
./Helpers/ReadDirectoryChangesPrivate.h \
|
||||
./Windows/NewBoxWindow.h \
|
||||
./Windows/RecoveryWindow.h \
|
||||
./Windows/PopUpWindow.h \
|
||||
|
@ -23,7 +26,8 @@ HEADERS += ./stdafx.h \
|
|||
./Windows/SettingsWindow.h \
|
||||
./Windows/OptionsWindow.h \
|
||||
./Windows/SelectBoxWindow.h \
|
||||
./Windows/FileBrowserWindow.h
|
||||
./Windows/FileBrowserWindow.h\
|
||||
./Wizards/SetupWizard.h
|
||||
|
||||
SOURCES += ./main.cpp \
|
||||
./stdafx.cpp \
|
||||
|
@ -31,6 +35,7 @@ SOURCES += ./main.cpp \
|
|||
./SbiePlusAPI.cpp \
|
||||
./SbieProcess.cpp \
|
||||
./BoxJob.cpp \
|
||||
./BoxMonitor.cpp \
|
||||
./Models/TraceModel.cpp \
|
||||
./Models/MonitorModel.cpp \
|
||||
./Models/SbieModel.cpp \
|
||||
|
@ -39,6 +44,8 @@ SOURCES += ./main.cpp \
|
|||
./Dialogs/MultiErrorDialog.cpp \
|
||||
./Helpers/FindTool.cpp \
|
||||
./Helpers/WinAdmin.cpp \
|
||||
./Helpers/ReadDirectoryChanges.cpp \
|
||||
./Helpers/ReadDirectoryChangesPrivate.cpp \
|
||||
./Helpers/WindowFromPointEx.cpp \
|
||||
./Windows/NewBoxWindow.cpp \
|
||||
./Windows/OptionsWindow.cpp \
|
||||
|
@ -57,7 +64,8 @@ SOURCES += ./main.cpp \
|
|||
./Windows/SettingsWindow.cpp \
|
||||
./Windows/SnapshotsWindow.cpp \
|
||||
./Windows/SelectBoxWindow.cpp \
|
||||
./Windows/FileBrowserWindow.cpp
|
||||
./Windows/FileBrowserWindow.cpp\
|
||||
./Wizards/SetupWizard.cpp
|
||||
|
||||
FORMS += ./Forms/NewBoxWindow.ui \
|
||||
./Forms/OptionsWindow.ui \
|
||||
|
|
|
@ -196,8 +196,11 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BoxJob.cpp" />
|
||||
<ClCompile Include="BoxMonitor.cpp" />
|
||||
<ClCompile Include="Dialogs\MultiErrorDialog.cpp" />
|
||||
<ClCompile Include="Helpers\FindTool.cpp" />
|
||||
<ClCompile Include="Helpers\ReadDirectoryChanges.cpp" />
|
||||
<ClCompile Include="Helpers\ReadDirectoryChangesPrivate.cpp" />
|
||||
<ClCompile Include="Helpers\WinAdmin.cpp" />
|
||||
<ClCompile Include="Helpers\WindowFromPointEx.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
|
@ -233,8 +236,10 @@
|
|||
<ClCompile Include="Windows\SelectBoxWindow.cpp" />
|
||||
<ClCompile Include="Windows\SettingsWindow.cpp" />
|
||||
<ClCompile Include="Windows\SnapshotsWindow.cpp" />
|
||||
<ClCompile Include="Wizards\SetupWizard.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="Wizards\SetupWizard.h" />
|
||||
<QtMoc Include="Windows\FileBrowserWindow.h" />
|
||||
<QtMoc Include="Windows\SelectBoxWindow.h" />
|
||||
<QtMoc Include="Views\TraceView.h" />
|
||||
|
@ -250,7 +255,12 @@
|
|||
<QtMoc Include="Models\TraceModel.h" />
|
||||
<QtMoc Include="Dialogs\MultiErrorDialog.h" />
|
||||
<QtMoc Include="BoxJob.h" />
|
||||
<ClInclude Include="..\version.h" />
|
||||
<QtMoc Include="BoxMonitor.h" />
|
||||
<ClInclude Include="Helpers\FindTool.h" />
|
||||
<ClInclude Include="Helpers\ReadDirectoryChanges.h" />
|
||||
<ClInclude Include="Helpers\ReadDirectoryChangesPrivate.h" />
|
||||
<ClInclude Include="Helpers\ThreadSafeQueue.h" />
|
||||
<ClInclude Include="Helpers\WinAdmin.h" />
|
||||
<QtMoc Include="Models\MonitorModel.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
<Extensions>ts</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Wizards">
|
||||
<UniqueIdentifier>{4bf40c7e-2ce4-4528-813c-3b48b8c56155}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
|
@ -147,6 +150,18 @@
|
|||
<ClCompile Include="Models\MonitorModel.cpp">
|
||||
<Filter>Models</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Wizards\SetupWizard.cpp">
|
||||
<Filter>Wizards</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Helpers\ReadDirectoryChanges.cpp">
|
||||
<Filter>Helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Helpers\ReadDirectoryChangesPrivate.cpp">
|
||||
<Filter>Helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BoxMonitor.cpp">
|
||||
<Filter>SandMan</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
|
@ -161,6 +176,18 @@
|
|||
<ClInclude Include="resource.h">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Helpers\ReadDirectoryChanges.h">
|
||||
<Filter>Helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Helpers\ReadDirectoryChangesPrivate.h">
|
||||
<Filter>Helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Helpers\ThreadSafeQueue.h">
|
||||
<Filter>Helpers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="SandMan.h">
|
||||
|
@ -217,6 +244,12 @@
|
|||
<QtMoc Include="Models\MonitorModel.h">
|
||||
<Filter>Models</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="Wizards\SetupWizard.h">
|
||||
<Filter>Wizards</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="BoxMonitor.h">
|
||||
<Filter>SandMan</Filter>
|
||||
</QtMoc>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtRcc Include="Resources\SandMan.qrc">
|
||||
|
|
|
@ -4,14 +4,18 @@
|
|||
#include "SandMan.h"
|
||||
#include "..\MiscHelpers\Common\Common.h"
|
||||
#include <windows.h>
|
||||
#include "BoxMonitor.h"
|
||||
|
||||
CSbiePlusAPI::CSbiePlusAPI(QObject* parent) : CSbieAPI(parent)
|
||||
{
|
||||
m_BoxMonitor = new CBoxMonitor();
|
||||
|
||||
m_JobCount = 0;
|
||||
}
|
||||
|
||||
CSbiePlusAPI::~CSbiePlusAPI()
|
||||
{
|
||||
delete m_BoxMonitor;
|
||||
}
|
||||
|
||||
CSandBox* CSbiePlusAPI::NewSandBox(const QString& BoxName, class CSbieAPI* pAPI)
|
||||
|
@ -94,7 +98,10 @@ CSandBoxPlus::CSandBoxPlus(const QString& BoxName, class CSbieAPI* pAPI) : CSand
|
|||
m_bApplicationCompartment = false;
|
||||
m_iUnsecureDebugging = 0;
|
||||
|
||||
m_TotalSize = theConf->GetValue("SizeCache/" + m_Name, -1).toLongLong();
|
||||
|
||||
m_SuspendRecovery = false;
|
||||
m_IsEmpty = false;
|
||||
|
||||
m_pOptionsWnd = NULL;
|
||||
m_pRecoveryWnd = NULL;
|
||||
|
@ -154,11 +161,56 @@ void CSandBoxPlus::UpdateDetails()
|
|||
CSandBox::UpdateDetails();
|
||||
}
|
||||
|
||||
void CSandBoxPlus::SetBoxPaths(const QString& FilePath, const QString& RegPath, const QString& IpcPath)
|
||||
{
|
||||
CSandBox::SetBoxPaths(FilePath, RegPath, IpcPath);
|
||||
m_IsEmpty = IsEmpty();
|
||||
|
||||
if (theConf->GetBool("Options/WatchBoxSize", false) && m_TotalSize == -1)
|
||||
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->AddBox(this);
|
||||
}
|
||||
|
||||
void CSandBoxPlus::UpdateSize()
|
||||
{
|
||||
m_TotalSize = -1;
|
||||
if(theConf->GetBool("Options/WatchBoxSize", false))
|
||||
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->AddBox(this);
|
||||
|
||||
m_IsEmpty = IsEmpty();
|
||||
}
|
||||
|
||||
void CSandBoxPlus::SetSize(quint64 Size)
|
||||
{
|
||||
m_TotalSize = Size;
|
||||
theConf->SetValue("SizeCache/" + m_Name, Size);
|
||||
}
|
||||
|
||||
void CSandBoxPlus::OpenBox()
|
||||
{
|
||||
CSandBox::OpenBox();
|
||||
|
||||
m_IsEmpty = false;
|
||||
|
||||
if (theConf->GetBool("Options/WatchBoxSize", false))
|
||||
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->AddBox(this, true);
|
||||
}
|
||||
|
||||
void CSandBoxPlus::CloseBox()
|
||||
{
|
||||
CSandBox::CloseBox();
|
||||
|
||||
m_SuspendRecovery = false;
|
||||
|
||||
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->CloseBox(this);
|
||||
}
|
||||
|
||||
SB_PROGRESS CSandBoxPlus::CleanBox()
|
||||
{
|
||||
((CSbiePlusAPI*)theAPI)->m_BoxMonitor->CloseBox(this, true);
|
||||
|
||||
SB_PROGRESS Status = CSandBox::CleanBox();
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
bool CSandBoxPlus::CheckUnsecureConfig() const
|
||||
|
@ -190,7 +242,7 @@ QString CSandBoxPlus::GetStatusStr() const
|
|||
|
||||
QStringList Status;
|
||||
|
||||
if (IsEmpty())
|
||||
if (m_IsEmpty)
|
||||
Status.append(tr("Empty"));
|
||||
|
||||
if (m_bApplicationCompartment)
|
||||
|
@ -513,6 +565,8 @@ void CSandBoxPlus::OnAsyncFinished()
|
|||
|
||||
if (!m_JobQueue.isEmpty())
|
||||
StartNextJob();
|
||||
else
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void CSandBoxPlus::OnAsyncMessage(const QString& Text)
|
||||
|
|
|
@ -29,6 +29,9 @@ protected:
|
|||
|
||||
int m_JobCount;
|
||||
QMultiMap<quint32, QString> m_WindowMap;
|
||||
|
||||
friend class CSandBoxPlus;
|
||||
class CBoxMonitor* m_BoxMonitor;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -44,8 +47,13 @@ public:
|
|||
|
||||
virtual void UpdateDetails();
|
||||
|
||||
virtual void SetBoxPaths(const QString& FilePath, const QString& RegPath, const QString& IpcPath);
|
||||
|
||||
virtual void OpenBox();
|
||||
virtual void CloseBox();
|
||||
|
||||
virtual SB_PROGRESS CleanBox();
|
||||
|
||||
virtual QString GetStatusStr() const;
|
||||
|
||||
virtual void SetLogApi(bool bEnable);
|
||||
|
@ -72,6 +80,10 @@ public:
|
|||
virtual void SetLeaderProgram(const QString& ProgName, bool bSet);
|
||||
virtual int IsLeaderProgram(const QString& ProgName);
|
||||
|
||||
virtual void UpdateSize();
|
||||
virtual quint64 GetSize() const { if(m_TotalSize == -1) return 0; return m_TotalSize; }
|
||||
virtual void SetSize(quint64 Size); //{ m_TotalSize = Size; }
|
||||
|
||||
virtual bool IsRecoverySuspended() const { return m_SuspendRecovery; }
|
||||
virtual void SetSuspendRecovery(bool bSet = true) { m_SuspendRecovery = bSet; }
|
||||
|
||||
|
@ -126,7 +138,10 @@ protected:
|
|||
bool m_bApplicationCompartment;
|
||||
int m_iUnsecureDebugging;
|
||||
|
||||
quint64 m_TotalSize;
|
||||
|
||||
bool m_SuspendRecovery;
|
||||
bool m_IsEmpty;
|
||||
QString m_StatusStr;
|
||||
|
||||
QSet<QString> m_RecentPrograms;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "../../MiscHelpers/Common/Common.h"
|
||||
#include "../Windows/OptionsWindow.h"
|
||||
#include "../Windows/SnapshotsWindow.h"
|
||||
#include <QFileIconProvider>
|
||||
#include "../../MiscHelpers/Common/CheckableMessageBox.h"
|
||||
#include "../Windows/RecoveryWindow.h"
|
||||
#include "../Windows/NewBoxWindow.h"
|
||||
|
@ -1351,8 +1350,6 @@ void CSbieView::UpdateRunMenu(const CSandBoxPtr& pBox)
|
|||
while (m_iMenuRun < m_pMenuRun->actions().count())
|
||||
m_pMenuRun->removeAction(m_pMenuRun->actions().at(m_iMenuRun));
|
||||
|
||||
QFileIconProvider IconProvider;
|
||||
|
||||
QStringList RunOptions = pBox->GetTextList("RunCommand", true);
|
||||
foreach(const QString& RunOption, RunOptions)
|
||||
{
|
||||
|
@ -1372,7 +1369,7 @@ void CSbieView::UpdateRunMenu(const CSandBoxPtr& pBox)
|
|||
if (Path.left(1) == "\\")
|
||||
Path.prepend(pBox->GetFileRoot());
|
||||
|
||||
pAction->setIcon(IconProvider.icon(QFileInfo(Path)));
|
||||
pAction->setIcon(m_IconProvider.icon(QFileInfo(Path)));
|
||||
|
||||
pAction->setData(NameCmd.second);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../../MiscHelpers/Common/PanelView.h"
|
||||
#include "../../MiscHelpers/Common/TreeviewEx.h"
|
||||
#include "../Models/SbieModel.h"
|
||||
#include <QFileIconProvider>
|
||||
|
||||
class CSbieView : public CPanelView
|
||||
{
|
||||
|
@ -152,4 +153,6 @@ private:
|
|||
QAction* m_pRemove;
|
||||
|
||||
int m_iMenuRun;
|
||||
|
||||
QFileIconProvider m_IconProvider;
|
||||
};
|
|
@ -218,7 +218,7 @@ void CFileBrowserWindow::OnFileMenu(const QPoint&)
|
|||
FileList.append(qMakePair(BoxedPath, RecoveryFolder + "\\" + FileName));
|
||||
}
|
||||
else {
|
||||
QString RealPath = theAPI->GetRealPath(m_pBox, BoxedPath);
|
||||
QString RealPath = theAPI->GetRealPath(m_pBox.data(), BoxedPath);
|
||||
FileList.append(qMakePair(BoxedPath, RealPath));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -312,12 +312,12 @@ int CRecoveryWindow::FindFiles(const QString& Folder)
|
|||
//foreach(const QString & Path, theAPI->GetBoxedPath(m_pBox, Folder))
|
||||
// Count += FindFiles(Folder, Path, Folder);
|
||||
//return Count;
|
||||
return FindFiles(theAPI->GetBoxedPath(m_pBox, Folder), Folder, Folder).first;
|
||||
return FindFiles(theAPI->GetBoxedPath(m_pBox.data(), Folder), Folder, Folder).first;
|
||||
}
|
||||
|
||||
int CRecoveryWindow::FindBoxFiles(const QString& Folder)
|
||||
{
|
||||
QString RealFolder = theAPI->GetRealPath(m_pBox, m_pBox->GetFileRoot() + Folder);
|
||||
QString RealFolder = theAPI->GetRealPath(m_pBox.data(), m_pBox->GetFileRoot() + Folder);
|
||||
if (RealFolder.isEmpty())
|
||||
return 0;
|
||||
return FindFiles(m_pBox->GetFileRoot() + Folder, RealFolder, RealFolder).first;
|
||||
|
|
|
@ -301,6 +301,8 @@ void CSettingsWindow::LoadSettings()
|
|||
ui.chkPanic->setChecked(theConf->GetBool("Options/EnablePanicKey", false));
|
||||
ui.keyPanic->setKeySequence(QKeySequence(theConf->GetString("Options/PanicKeySequence", "Shift+Pause")));
|
||||
|
||||
ui.chkMonitorSize->setChecked(theConf->GetBool("Options/WatchBoxSize", false));
|
||||
|
||||
ui.chkWatchConfig->setChecked(theConf->GetBool("Options/WatchIni", true));
|
||||
|
||||
|
||||
|
@ -458,6 +460,8 @@ void CSettingsWindow::SaveSettings()
|
|||
theConf->SetValue("Options/EnablePanicKey", ui.chkPanic->isChecked());
|
||||
theConf->SetValue("Options/PanicKeySequence", ui.keyPanic->keySequence().toString());
|
||||
|
||||
theConf->SetValue("Options/WatchBoxSize", ui.chkMonitorSize->isChecked());
|
||||
|
||||
theConf->SetValue("Options/WatchIni", ui.chkWatchConfig->isChecked());
|
||||
|
||||
theConf->SetValue("Options/SysTrayIcon", ui.cmbSysTray->currentIndex());
|
||||
|
@ -573,6 +577,41 @@ void CSettingsWindow::SaveSettings()
|
|||
|
||||
QPalette palette = QApplication::palette();
|
||||
|
||||
if (theGUI->m_DarkTheme)
|
||||
palette.setColor(QPalette::Text, Qt::black);
|
||||
|
||||
ui.lblCertExp->setVisible(false);
|
||||
|
||||
bool bRet = ApplyCertificate(Certificate, this);
|
||||
|
||||
if (Certificate.isEmpty())
|
||||
palette.setColor(QPalette::Base, Qt::white);
|
||||
else if (!bRet)
|
||||
palette.setColor(QPalette::Base, QColor(255, 192, 192));
|
||||
else if (g_CertInfo.expired || g_CertInfo.outdated) {
|
||||
palette.setColor(QPalette::Base, QColor(255, 255, 192));
|
||||
ui.lblCertExp->setVisible(true);
|
||||
}
|
||||
else
|
||||
palette.setColor(QPalette::Base, QColor(192, 255, 192));
|
||||
|
||||
ui.txtCertificate->setPalette(palette);
|
||||
}
|
||||
|
||||
m_CertChanged = false;
|
||||
}
|
||||
|
||||
theConf->SetValue("Options/CheckForUpdates", CSettingsWindow__Chk2Int(ui.chkAutoUpdate->checkState()));
|
||||
theConf->SetValue("Options/DownloadUpdates", CSettingsWindow__Chk2Int(ui.chkAutoDownload->checkState()));
|
||||
//theConf->SetValue("Options/InstallUpdates", CSettingsWindow__Chk2Int(ui.chkAutoInstall->checkState()));
|
||||
|
||||
theConf->SetValue("Options/NoSupportCheck", ui.chkNoCheck->isChecked());
|
||||
|
||||
emit OptionsChanged();
|
||||
}
|
||||
|
||||
bool CSettingsWindow::ApplyCertificate(const QByteArray &Certificate, QWidget* widget)
|
||||
{
|
||||
QString CertPath = theAPI->GetSbiePath() + "\\Certificate.dat";
|
||||
if (!Certificate.isEmpty()) {
|
||||
|
||||
|
@ -597,67 +636,43 @@ void CSettingsWindow::SaveSettings()
|
|||
WindowsMoveFile(TempPath.replace("/", "\\"), CertPath.replace("/", "\\"));
|
||||
}
|
||||
else {
|
||||
Certificate.clear();
|
||||
QMessageBox::critical(this, "Sandboxie-Plus", tr("This does not look like a certificate, please enter the entire certificate, not just a portion of it."));
|
||||
QMessageBox::critical(widget, "Sandboxie-Plus", tr("This does not look like a certificate, please enter the entire certificate not just a portion of it."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(!g_Certificate.isEmpty()){
|
||||
WindowsMoveFile(CertPath.replace("/", "\\"), "");
|
||||
}
|
||||
|
||||
if (theGUI->m_DarkTheme)
|
||||
palette.setColor(QPalette::Text, Qt::black);
|
||||
|
||||
ui.lblCertExp->setVisible(false);
|
||||
|
||||
if (Certificate.isEmpty())
|
||||
{
|
||||
palette.setColor(QPalette::Base, Qt::white);
|
||||
}
|
||||
else if (!theAPI->ReloadCert().IsError())
|
||||
return false;
|
||||
|
||||
if (!theAPI->ReloadCert().IsError())
|
||||
{
|
||||
g_FeatureFlags = theAPI->GetFeatureFlags();
|
||||
theGUI->UpdateCertState();
|
||||
|
||||
if (g_CertInfo.expired || g_CertInfo.outdated) {
|
||||
if(g_CertInfo.expired)
|
||||
QMessageBox::information(this, "Sandboxie-Plus", tr("This certificate is unfortunately expired."));
|
||||
QMessageBox::information(widget, "Sandboxie-Plus", tr("This certificate is unfortunately expired."));
|
||||
else
|
||||
QMessageBox::information(this, "Sandboxie-Plus", tr("This certificate is unfortunately outdated."));
|
||||
|
||||
palette.setColor(QPalette::Base, QColor(255, 255, 192));
|
||||
ui.lblCertExp->setVisible(true);
|
||||
QMessageBox::information(widget, "Sandboxie-Plus", tr("This certificate is unfortunately outdated."));
|
||||
}
|
||||
else {
|
||||
QMessageBox::information(this, "Sandboxie-Plus", tr("Thank you for supporting the development of Sandboxie-Plus."));
|
||||
|
||||
palette.setColor(QPalette::Base, QColor(192, 255, 192));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "Sandboxie-Plus", tr("This support certificate is not valid."));
|
||||
|
||||
palette.setColor(QPalette::Base, QColor(255, 192, 192));
|
||||
Certificate.clear();
|
||||
g_CertInfo.State = 0;
|
||||
QMessageBox::information(widget, "Sandboxie-Plus", tr("Thank you for supporting the development of Sandboxie-Plus."));
|
||||
}
|
||||
|
||||
g_Certificate = Certificate;
|
||||
|
||||
ui.txtCertificate->setPalette(palette);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(widget, "Sandboxie-Plus", tr("This support certificate is not valid."));
|
||||
|
||||
m_CertChanged = false;
|
||||
g_CertInfo.State = 0;
|
||||
g_Certificate.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
theConf->SetValue("Options/CheckForUpdates", CSettingsWindow__Chk2Int(ui.chkAutoUpdate->checkState()));
|
||||
theConf->SetValue("Options/DownloadUpdates", CSettingsWindow__Chk2Int(ui.chkAutoDownload->checkState()));
|
||||
//theConf->SetValue("Options/InstallUpdates", CSettingsWindow__Chk2Int(ui.chkAutoInstall->checkState()));
|
||||
|
||||
theConf->SetValue("Options/NoSupportCheck", ui.chkNoCheck->isChecked());
|
||||
|
||||
emit OptionsChanged();
|
||||
}
|
||||
|
||||
void CSettingsWindow::apply()
|
||||
|
|
|
@ -24,6 +24,8 @@ public:
|
|||
virtual void accept() {}
|
||||
virtual void reject();
|
||||
|
||||
static bool ApplyCertificate(const QByteArray &Certificate, QWidget* widget);
|
||||
|
||||
static void LoadCertificate();
|
||||
|
||||
signals:
|
||||
|
|
|
@ -0,0 +1,327 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
#include "SetupWizard.h"
|
||||
#include "../MiscHelpers/Common/Common.h"
|
||||
#include "../Windows/SettingsWindow.h"
|
||||
#include "../SandMan.h"
|
||||
#include "Helpers/WinAdmin.h"
|
||||
|
||||
QString emailRegExp = QStringLiteral(".+@.+");
|
||||
|
||||
CSetupWizard::CSetupWizard(QWidget *parent)
|
||||
: QWizard(parent)
|
||||
{
|
||||
setPage(Page_Intro, new CIntroPage);
|
||||
setPage(Page_Certificate, new CCertificatePage);
|
||||
setPage(Page_Shell, new CShellPage);
|
||||
setPage(Page_Finish, new CFinishPage);
|
||||
|
||||
setWizardStyle(ModernStyle);
|
||||
//setOption(HaveHelpButton, true);
|
||||
setPixmap(QWizard::LogoPixmap, QPixmap(":/SandMan.png").scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
|
||||
connect(this, &QWizard::helpRequested, this, &CSetupWizard::showHelp);
|
||||
|
||||
setWindowTitle(tr("Setup Wizard"));
|
||||
}
|
||||
|
||||
void CSetupWizard::showHelp()
|
||||
{
|
||||
static QString lastHelpMessage;
|
||||
|
||||
QString message;
|
||||
|
||||
switch (currentId()) {
|
||||
case Page_Intro:
|
||||
message = tr("The decision you make here will affect which page you get to see next.");
|
||||
break;
|
||||
default:
|
||||
message = tr("This help is likely not to be of any help.");
|
||||
}
|
||||
|
||||
if (lastHelpMessage == message)
|
||||
message = tr("Sorry, I already gave what help I could.");
|
||||
|
||||
QMessageBox::information(this, tr("Setup Wizard Help"), message);
|
||||
|
||||
lastHelpMessage = message;
|
||||
}
|
||||
|
||||
bool CSetupWizard::ShowWizard()
|
||||
{
|
||||
CSetupWizard wizard;
|
||||
if (!wizard.exec())
|
||||
return false;
|
||||
|
||||
//bool useBusiness = wizard.field("useBusiness").toBool();
|
||||
//QString Certificate = wizard.field("useCertificate").toString();
|
||||
//bool isEvaluate = wizard.field("isEvaluate").toBool();
|
||||
|
||||
AutorunEnable(wizard.field("isAutoStart").toBool());
|
||||
|
||||
if (wizard.field("useContecxtMenu").toBool())
|
||||
CSettingsWindow__AddContextMenu();
|
||||
|
||||
if (wizard.field("useBrowserIcon").toBool())
|
||||
CSettingsWindow__AddBrowserIcon();
|
||||
|
||||
if (wizard.field("isUpdate").toBool()) {
|
||||
theConf->SetValue("Options/CheckForUpdates", 1);
|
||||
theConf->SetValue("Options/DownloadUpdates", 1);
|
||||
theConf->SetValue("Options/InstallUpdates", 1);
|
||||
}
|
||||
|
||||
theConf->SetValue("Options/WizardLevel", 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CIntroPage
|
||||
//
|
||||
|
||||
CIntroPage::CIntroPage(QWidget *parent)
|
||||
: QWizardPage(parent)
|
||||
{
|
||||
setTitle(tr("Introduction"));
|
||||
setPixmap(QWizard::WatermarkPixmap, QPixmap(":/SideLogo.png"));
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
QLabel* pTopLabel = new QLabel(tr("Welcome to the Setup Wizard. This wizard will help you to configure your copy of <b>Sandboxie-Plus</b>. "
|
||||
"You can start this wizard at any time from the Box->Maintenance if you do not wish to complete it now."));
|
||||
pTopLabel->setWordWrap(true);
|
||||
layout->addWidget(pTopLabel);
|
||||
|
||||
QWidget* pSpace = new QWidget();
|
||||
pSpace->setMinimumHeight(16);
|
||||
layout->addWidget(pSpace);
|
||||
|
||||
int BusinessUse = theConf->GetInt("Options/BusinessUse", 2);
|
||||
|
||||
m_pLabel = new QLabel(tr("Select how you would like to use Sandboxie-Plus"));
|
||||
layout->addWidget(m_pLabel);
|
||||
|
||||
m_pPersonalRadio = new QRadioButton(tr("&Personally for private non comertial use"));
|
||||
layout->addWidget(m_pPersonalRadio);
|
||||
connect(m_pPersonalRadio, SIGNAL(toggled(bool)), this, SIGNAL(completeChanged()));
|
||||
registerField("usePersonal", m_pPersonalRadio);
|
||||
|
||||
m_pBusinessRadio = new QRadioButton(tr("&Commercially for business or enterprise use"));
|
||||
layout->addWidget(m_pBusinessRadio);
|
||||
connect(m_pBusinessRadio, SIGNAL(toggled(bool)), this, SIGNAL(completeChanged()));
|
||||
registerField("useBusiness", m_pBusinessRadio);
|
||||
|
||||
if (BusinessUse != 2) {
|
||||
m_pLabel->setEnabled(false);
|
||||
m_pPersonalRadio->setChecked(BusinessUse == 0);
|
||||
m_pPersonalRadio->setEnabled(false);
|
||||
m_pBusinessRadio->setChecked(BusinessUse == 1);
|
||||
m_pBusinessRadio->setEnabled(false);
|
||||
}
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
int CIntroPage::nextId() const
|
||||
{
|
||||
if(g_Certificate.isEmpty())
|
||||
return CSetupWizard::Page_Certificate;
|
||||
return CSetupWizard::Page_Shell;
|
||||
}
|
||||
|
||||
bool CIntroPage::isComplete() const
|
||||
{
|
||||
if (m_pLabel->isEnabled() && !m_pPersonalRadio->isChecked() && !m_pBusinessRadio->isChecked())
|
||||
return false;
|
||||
return QWizardPage::isComplete();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CCertificatePage
|
||||
//
|
||||
|
||||
CCertificatePage::CCertificatePage(QWidget *parent)
|
||||
: QWizardPage(parent)
|
||||
{
|
||||
setTitle(tr("Install your <b>Sandboxie-Plus</b> support certificate"));
|
||||
setSubTitle(tr("If you have a supporter certificate, please fill it into the field below."));
|
||||
|
||||
QGridLayout *layout = new QGridLayout;
|
||||
|
||||
m_pTopLabel = new QLabel();
|
||||
m_pTopLabel->setWordWrap(true);
|
||||
layout->addWidget(m_pTopLabel);
|
||||
|
||||
m_pCertificate = new QPlainTextEdit();
|
||||
m_pCertificate->setMaximumSize(QSize(16777215, 73));
|
||||
m_pCertificate->setPlaceholderText(
|
||||
"NAME: User Name\n"
|
||||
"LEVEL: ULTIMATE\n"
|
||||
"DATE: dd.mm.yyyy\n"
|
||||
"UPDATEKEY: 00000000000000000000000000000000\n"
|
||||
"SIGNATURE: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
||||
);
|
||||
//layout->addWidget(m_pCertificate); // we dont show this page when there already is a certificat present
|
||||
connect(m_pCertificate, SIGNAL(textChanged()), this, SIGNAL(completeChanged()));
|
||||
registerField("useCertificate", m_pCertificate, "plainText");
|
||||
|
||||
m_pEvaluate = new QCheckBox(tr("Start evaluation without a certificate for a limited periode of time."));
|
||||
layout->addWidget(m_pEvaluate);
|
||||
connect(m_pEvaluate, SIGNAL(toggled(bool)), this, SIGNAL(completeChanged()));
|
||||
registerField("isEvaluate", m_pEvaluate);
|
||||
|
||||
layout->addWidget(new QWidget());
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void CCertificatePage::initializePage()
|
||||
{
|
||||
m_pCertificate->setPlainText(g_Certificate);
|
||||
|
||||
if (field("useBusiness").toBool())
|
||||
{
|
||||
theConf->SetValue("Options/BusinessUse", 1);
|
||||
|
||||
m_pTopLabel->setText(
|
||||
tr("To use <b>Sandboxie-Plus</b> in a business setting an apropriate business use <a href=\"https://sandboxie-plus.com/go.php?to=sbie-get-cert\">support certificate</a> is required. "
|
||||
"If you do not yet have the required certificate(s) you can get those from the <a href=\"https://xanasoft.com/shop/\">xanasoft.com web shop</a>.")
|
||||
);
|
||||
|
||||
m_pEvaluate->setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
theConf->SetValue("Options/BusinessUse", 0);
|
||||
|
||||
m_pTopLabel->setText(
|
||||
tr("<b>Sandboxie-Plus</b> provides additional features and box types exclusively to <u>project supporters</u>. "
|
||||
"Boxes like the Privacy Enhanced boxes <b><font color='red'>protect user data from illicit access</font></b> by the sandboxed programs. "
|
||||
"If you are not yet a supporter then please consider <a href=\"https://sandboxie-plus.com/go.php?to=sbie-get-cert\">supporting the project</a> "
|
||||
"to to ensure furtehr developement of sandboxie and to receive a <a href=\"https://sandboxie-plus.com/go.php?to=sbie-cert\">supporter certificate</a>.")
|
||||
);
|
||||
|
||||
m_pEvaluate->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
int CCertificatePage::nextId() const
|
||||
{
|
||||
return CSetupWizard::Page_Shell;
|
||||
}
|
||||
|
||||
bool CCertificatePage::isComplete() const
|
||||
{
|
||||
if (field("useBusiness").toBool())
|
||||
{
|
||||
m_pCertificate->setEnabled(!m_pEvaluate->isChecked());
|
||||
if (m_pCertificate->toPlainText().isEmpty() && !m_pEvaluate->isChecked())
|
||||
return false;
|
||||
}
|
||||
return QWizardPage::isComplete();
|
||||
}
|
||||
|
||||
bool CCertificatePage::validatePage()
|
||||
{
|
||||
QByteArray Certificate = m_pCertificate->toPlainText().toLatin1();
|
||||
if (!m_pEvaluate->isChecked() && !Certificate.isEmpty() && g_Certificate != Certificate) {
|
||||
return CSettingsWindow::ApplyCertificate(Certificate, this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CShellPage
|
||||
//
|
||||
|
||||
CShellPage::CShellPage(QWidget *parent)
|
||||
: QWizardPage(parent)
|
||||
{
|
||||
setTitle(tr("Configure <b>Sandboxie-Plus</b> shell integration"));
|
||||
setSubTitle(tr("Configure how Sandboxie-Plus should integrate with your system."));
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
|
||||
m_pAutoStart = new QCheckBox(tr("Start UI with Windows"));
|
||||
m_pAutoStart->setChecked(true);
|
||||
layout->addWidget(m_pAutoStart);
|
||||
registerField("isAutoStart", m_pAutoStart);
|
||||
|
||||
m_pContecxtMenu = new QCheckBox(tr("Add 'Run Sandboxed' to the explorer context menu"));
|
||||
m_pContecxtMenu->setChecked(true);
|
||||
layout->addWidget(m_pContecxtMenu);
|
||||
registerField("useContecxtMenu", m_pContecxtMenu);
|
||||
|
||||
m_pBrowserIcon = new QCheckBox(tr("Add desktop shortcut for starting Web browser under Sandboxie"));
|
||||
m_pBrowserIcon->setChecked(true);
|
||||
layout->addWidget(m_pBrowserIcon);
|
||||
registerField("useBrowserIcon", m_pBrowserIcon);
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
int CShellPage::nextId() const
|
||||
{
|
||||
return CSetupWizard::Page_Finish;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CFinishPage
|
||||
//
|
||||
|
||||
CFinishPage::CFinishPage(QWidget *parent)
|
||||
: QWizardPage(parent)
|
||||
{
|
||||
setTitle(tr("Complete Your Configuration"));
|
||||
setPixmap(QWizard::WatermarkPixmap, QPixmap(":/SideLogo.png"));
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
|
||||
m_pLabel = new QLabel;
|
||||
m_pLabel->setWordWrap(true);
|
||||
m_pLabel->setText(tr("Almost complete, click Finish to apply all selected options and finisch the wizard."));
|
||||
layout->addWidget(m_pLabel);
|
||||
|
||||
QWidget* pSpacer = new QWidget();
|
||||
pSpacer->setMinimumHeight(16);
|
||||
layout->addWidget(pSpacer);
|
||||
|
||||
//QLabel* pLabel = new QLabel;
|
||||
//pLabel->setWordWrap(true);
|
||||
//pLabel->setText(tr("Like with any other security product it's important to keep your Sandboxie-Plus up to date."));
|
||||
//layout->addWidget(pLabel);
|
||||
|
||||
m_pUpdate = new QCheckBox(tr("Keep Sandboxie-Plus up to date."));
|
||||
m_pUpdate->setChecked(true);
|
||||
layout->addWidget(m_pUpdate);
|
||||
registerField("isUpdate", m_pUpdate);
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
int CFinishPage::nextId() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CFinishPage::initializePage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//void ConclusionPage::setVisible(bool visible)
|
||||
//{
|
||||
// QWizardPage::setVisible(visible);
|
||||
//
|
||||
// if (visible) {
|
||||
// wizard()->setButtonText(QWizard::CustomButton1, tr("&Print"));
|
||||
// wizard()->setOption(QWizard::HaveCustomButton1, true);
|
||||
// connect(wizard(), &QWizard::customButtonClicked,
|
||||
// this, &ConclusionPage::printButtonClicked);
|
||||
// } else {
|
||||
// wizard()->setOption(QWizard::HaveCustomButton1, false);
|
||||
// disconnect(wizard(), &QWizard::customButtonClicked,
|
||||
// this, &ConclusionPage::printButtonClicked);
|
||||
// }
|
||||
//}
|
|
@ -0,0 +1,107 @@
|
|||
#pragma once
|
||||
|
||||
#include <QWizard>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QCheckBox;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QRadioButton;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class CSetupWizard : public QWizard
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum { Page_Intro, Page_Certificate, Page_Shell, Page_Finish };
|
||||
|
||||
CSetupWizard(QWidget *parent = nullptr);
|
||||
|
||||
static bool ShowWizard();
|
||||
|
||||
private slots:
|
||||
void showHelp();
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CIntroPage
|
||||
//
|
||||
|
||||
class CIntroPage : public QWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CIntroPage(QWidget *parent = nullptr);
|
||||
|
||||
int nextId() const override;
|
||||
bool isComplete() const override;
|
||||
|
||||
private:
|
||||
QLabel* m_pLabel;
|
||||
QRadioButton *m_pPersonalRadio;
|
||||
QRadioButton *m_pBusinessRadio;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CCertificatePage
|
||||
//
|
||||
|
||||
class CCertificatePage : public QWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CCertificatePage(QWidget *parent = nullptr);
|
||||
|
||||
void initializePage() override;
|
||||
int nextId() const override;
|
||||
bool isComplete() const override;
|
||||
bool validatePage() override;
|
||||
|
||||
private:
|
||||
QLabel* m_pTopLabel;
|
||||
QPlainTextEdit* m_pCertificate;
|
||||
QCheckBox* m_pEvaluate;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CShellPage
|
||||
//
|
||||
|
||||
class CShellPage : public QWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CShellPage(QWidget *parent = nullptr);
|
||||
|
||||
int nextId() const override;
|
||||
|
||||
private:
|
||||
QCheckBox *m_pAutoStart;
|
||||
QCheckBox *m_pContecxtMenu;
|
||||
QCheckBox *m_pBrowserIcon;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CFinishPage
|
||||
//
|
||||
|
||||
class CFinishPage : public QWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CFinishPage(QWidget *parent = nullptr);
|
||||
|
||||
void initializePage() override;
|
||||
int nextId() const override;
|
||||
//void setVisible(bool visible) override;
|
||||
|
||||
private:
|
||||
QLabel *m_pLabel;
|
||||
QCheckBox *m_pUpdate;
|
||||
};
|
||||
|
|
@ -106,6 +106,7 @@ using namespace std;
|
|||
#include <QColorDialog>
|
||||
#include <QToolButton>
|
||||
#include <QScreen>
|
||||
#include <QRadioButton>
|
||||
|
||||
// other includes
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#define VERSION_MJR 1
|
||||
#define VERSION_MIN 0
|
||||
#define VERSION_REV 22
|
||||
#define VERSION_MIN 1
|
||||
#define VERSION_REV 0
|
||||
#define VERSION_UPD 0
|
||||
|
||||
#ifndef STR
|
||||
|
|
Loading…
Reference in New Issue