mirror of
https://github.com/CloudDelphi/Virtual-File-System
synced 2025-12-19 09:53:54 +01:00
Added support for NtCreate/OpenFile, NtClose and hooks uninstalling
This commit is contained in:
parent
360fddaa46
commit
21c4b1df1c
1
Tests/Fs/Mods/FullyVirtual_2/Hobbots/mms.cfg
Normal file
1
Tests/Fs/Mods/FullyVirtual_2/Hobbots/mms.cfg
Normal file
@ -0,0 +1 @@
|
|||||||
|
It was a pleasure to override you, friend!
|
||||||
@ -4,9 +4,9 @@ unit VfsIntegratedTest;
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
SysUtils, TestFramework, Windows,
|
SysUtils, TestFramework, Windows,
|
||||||
Utils, WinUtils, ConsoleApi,
|
Utils, WinUtils, ConsoleApi, Files,
|
||||||
VfsUtils, VfsBase, VfsDebug,
|
VfsUtils, VfsBase, VfsDebug,
|
||||||
VfsControl;
|
VfsOpenFiles, VfsControl, DlgMes;
|
||||||
|
|
||||||
type
|
type
|
||||||
TestIntegrated = class (TTestCase)
|
TestIntegrated = class (TTestCase)
|
||||||
@ -22,8 +22,10 @@ type
|
|||||||
published
|
published
|
||||||
procedure TestGetFileAttributes;
|
procedure TestGetFileAttributes;
|
||||||
procedure TestGetFileAttributesEx;
|
procedure TestGetFileAttributesEx;
|
||||||
|
procedure TestFilesOpenClose;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
(***) implementation (***)
|
(***) implementation (***)
|
||||||
|
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ end;
|
|||||||
|
|
||||||
function TestIntegrated.GetRootDir: string;
|
function TestIntegrated.GetRootDir: string;
|
||||||
begin
|
begin
|
||||||
result := SysUtils.ExtractFileDir(WinUtils.GetExePath) + '\Tests\Fs';
|
result := VfsUtils.NormalizePath(SysUtils.ExtractFileDir(WinUtils.GetExePath) + '\Tests\Fs');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TestIntegrated.SetUp;
|
procedure TestIntegrated.SetUp;
|
||||||
@ -42,22 +44,20 @@ var
|
|||||||
RootDir: string;
|
RootDir: string;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if not Inited then begin
|
RootDir := Self.GetRootDir;
|
||||||
Inited := true;
|
VfsBase.ResetVfs();
|
||||||
RootDir := Self.GetRootDir;
|
VfsBase.MapDir(RootDir, RootDir + '\Mods\FullyVirtual_2', DONT_OVERWRITE_EXISTING);
|
||||||
VfsBase.ResetVfs();
|
VfsBase.MapDir(RootDir, RootDir + '\Mods\FullyVirtual', DONT_OVERWRITE_EXISTING);
|
||||||
VfsBase.MapDir(RootDir, RootDir + '\Mods\FullyVirtual', DONT_OVERWRITE_EXISTING);
|
VfsBase.MapDir(RootDir, RootDir + '\Mods\B', DONT_OVERWRITE_EXISTING);
|
||||||
VfsBase.MapDir(RootDir, RootDir + '\Mods\B', DONT_OVERWRITE_EXISTING);
|
VfsBase.MapDir(RootDir, RootDir + '\Mods\A', DONT_OVERWRITE_EXISTING);
|
||||||
VfsBase.MapDir(RootDir, RootDir + '\Mods\A', DONT_OVERWRITE_EXISTING);
|
VfsBase.MapDir(RootDir, RootDir + '\Mods\Apache', DONT_OVERWRITE_EXISTING);
|
||||||
VfsBase.MapDir(RootDir, RootDir + '\Mods\Apache', DONT_OVERWRITE_EXISTING);
|
VfsDebug.SetLoggingProc(LogSomething);
|
||||||
VfsDebug.SetLoggingProc(LogSomething);
|
VfsControl.RunVfs(VfsBase.SORT_FIFO);
|
||||||
VfsControl.RunVfs(VfsBase.SORT_FIFO);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TestIntegrated.TearDown;
|
procedure TestIntegrated.TearDown;
|
||||||
begin
|
begin
|
||||||
VfsBase.PauseVfs();
|
VfsBase.ResetVfs();
|
||||||
VfsDebug.SetLoggingProc(nil);
|
VfsDebug.SetLoggingProc(nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -112,11 +112,58 @@ var
|
|||||||
begin
|
begin
|
||||||
RootDir := Self.GetRootDir;
|
RootDir := Self.GetRootDir;
|
||||||
CheckEquals(-1, GetFileSize(RootDir + '\non-existing.non'), '{1}');
|
CheckEquals(-1, GetFileSize(RootDir + '\non-existing.non'), '{1}');
|
||||||
CheckEquals(47, GetFileSize(RootDir + '\Hobbots\mms.cfg'), '{2}');
|
CheckEquals(42, GetFileSize(RootDir + '\Hobbots\mms.cfg'), '{2}');
|
||||||
CheckEquals(22, GetFileSize(RootDir + '\503.html'), '{3}');
|
CheckEquals(22, GetFileSize(RootDir + '\503.html'), '{3}');
|
||||||
CheckEquals(318, GetFileSize(RootDir + '\default'), '{4}');
|
CheckEquals(318, GetFileSize(RootDir + '\default'), '{4}');
|
||||||
end; // .procedure TestIntegrated.TestGetFileAttributesEx;
|
end; // .procedure TestIntegrated.TestGetFileAttributesEx;
|
||||||
|
|
||||||
|
procedure TestIntegrated.TestFilesOpenClose;
|
||||||
|
var
|
||||||
|
CurrDir: string;
|
||||||
|
RootDir: string;
|
||||||
|
FileData: string;
|
||||||
|
hFile: integer;
|
||||||
|
|
||||||
|
function OpenFile (const Path: string): integer;
|
||||||
|
begin
|
||||||
|
result := SysUtils.FileOpen(Path, fmOpenRead or fmShareDenyNone);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
CurrDir := SysUtils.GetCurrentDir;
|
||||||
|
RootDir := Self.GetRootDir;
|
||||||
|
|
||||||
|
try
|
||||||
|
Check(SysUtils.SetCurrentDir(RootDir), 'Setting current directory to real path must succeed');
|
||||||
|
|
||||||
|
Check(OpenFile(RootDir + '\non-existing.non') <= 0, 'Opening non-existing file must fail');
|
||||||
|
|
||||||
|
hFile := OpenFile(RootDir + '\Hobbots\mms.cfg');
|
||||||
|
Check(hFile > 0, 'Opening fully virtual file must succeed');
|
||||||
|
CheckEquals(RootDir + '\Hobbots\mms.cfg', VfsOpenFiles.GetOpenedFilePath(hFile), 'There must be created a corresponding TOpenedFile record for opened file handle with valid virtual path');
|
||||||
|
SysUtils.FileClose(hFile);
|
||||||
|
CheckEquals('', VfsOpenFiles.GetOpenedFilePath(hFile), 'TOpenedFile record must be destroyed on file handle closing {1}');
|
||||||
|
|
||||||
|
hFile := OpenFile('Hobbots\mms.cfg');
|
||||||
|
Check(hFile > 0, 'Opening fully virtual file using relative path must succeed');
|
||||||
|
CheckEquals(RootDir + '\Hobbots\mms.cfg', VfsOpenFiles.GetOpenedFilePath(hFile), 'There must be created a corresponding TOpenedFile record for opened file handle with valid virtual path when relative path was used');
|
||||||
|
SysUtils.FileClose(hFile);
|
||||||
|
CheckEquals('', VfsOpenFiles.GetOpenedFilePath(hFile), 'TOpenedFile record must be destroyed on file handle closing {2}');
|
||||||
|
|
||||||
|
Check(SysUtils.SetCurrentDir(RootDir + '\Hobbots'), 'Setting current durectory to fully virtual must succeed');
|
||||||
|
hFile := OpenFile('mms.cfg');
|
||||||
|
Check(hFile > 0, 'Opening fully virtual file in fully virtual directory using relative path must succeed');
|
||||||
|
CheckEquals(RootDir + '\Hobbots\mms.cfg', VfsOpenFiles.GetOpenedFilePath(hFile), 'There must be created a corresponding TOpenedFile record for opened file handle with valid virtual path when relative path was used for fully virtual directory');
|
||||||
|
SysUtils.FileClose(hFile);
|
||||||
|
CheckEquals('', VfsOpenFiles.GetOpenedFilePath(hFile), 'TOpenedFile record must be destroyed on file handle closing {3}');
|
||||||
|
|
||||||
|
Check(Files.ReadFileContents('mms.cfg', FileData), 'File mms.cfg must be readable');
|
||||||
|
CheckEquals('It was a pleasure to override you, friend!', FileData);
|
||||||
|
finally
|
||||||
|
SysUtils.SetCurrentDir(CurrDir);
|
||||||
|
end; // .try
|
||||||
|
end; // .procedure TestIntegrated.TestFilesOpenClose;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
RegisterTest(TestIntegrated.Suite);
|
RegisterTest(TestIntegrated.Suite);
|
||||||
end.
|
end.
|
||||||
13
VfsBase.pas
13
VfsBase.pas
@ -530,15 +530,10 @@ begin
|
|||||||
try
|
try
|
||||||
DisableVfsForThread;
|
DisableVfsForThread;
|
||||||
result := Func(Arg);
|
result := Func(Arg);
|
||||||
except
|
finally
|
||||||
on E: Exception do begin
|
RestoreVfsForThread;
|
||||||
RestoreVfsForThread;
|
end;
|
||||||
raise E;
|
end;
|
||||||
end;
|
|
||||||
end; // .try
|
|
||||||
|
|
||||||
RestoreVfsForThread;
|
|
||||||
end; // .with
|
|
||||||
end; // .function CallWithoutVfs
|
end; // .function CallWithoutVfs
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|||||||
115
VfsHooks.pas
115
VfsHooks.pas
@ -32,6 +32,13 @@ var
|
|||||||
NativeNtClose: WinNative.TNtClose;
|
NativeNtClose: WinNative.TNtClose;
|
||||||
NativeNtQueryDirectoryFile: WinNative.TNtQueryDirectoryFile;
|
NativeNtQueryDirectoryFile: WinNative.TNtQueryDirectoryFile;
|
||||||
|
|
||||||
|
NtQueryAttributesFilePatch: VfsPatching.TAppliedPatch;
|
||||||
|
NtQueryFullAttributesFilePatch: VfsPatching.TAppliedPatch;
|
||||||
|
NtOpenFilePatch: VfsPatching.TAppliedPatch;
|
||||||
|
NtCreateFilePatch: VfsPatching.TAppliedPatch;
|
||||||
|
NtClosePatch: VfsPatching.TAppliedPatch;
|
||||||
|
NtQueryDirectoryFilePatch: VfsPatching.TAppliedPatch;
|
||||||
|
|
||||||
|
|
||||||
(* There is no 100% portable and reliable way to get file path by handle, unless file creation/opening
|
(* There is no 100% portable and reliable way to get file path by handle, unless file creation/opening
|
||||||
was tracked. Thus we rely heavily on VfsOpenFiles.
|
was tracked. Thus we rely heavily on VfsOpenFiles.
|
||||||
@ -209,11 +216,9 @@ var
|
|||||||
ReplacedObjAttrs: WinNative.TObjectAttributes;
|
ReplacedObjAttrs: WinNative.TObjectAttributes;
|
||||||
HadTrailingDelim: boolean;
|
HadTrailingDelim: boolean;
|
||||||
|
|
||||||
FileInfo: Windows.TWin32FindDataW;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if VfsDebug.LoggingEnabled then begin
|
if VfsDebug.LoggingEnabled then begin
|
||||||
WriteLog('NtCreateFile', ObjectAttributes.ObjectName.ToWideStr());
|
WriteLog('[ENTER] NtCreateFile', Format('Access: 0x%x. CreateDisposition: 0x%x'#13#10'Path: "%s"', [Int(DesiredAccess), Int(CreateDisposition), ObjectAttributes.ObjectName.ToWideStr()]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ReplacedObjAttrs := ObjectAttributes^;
|
ReplacedObjAttrs := ObjectAttributes^;
|
||||||
@ -222,7 +227,7 @@ begin
|
|||||||
RedirectedPath := '';
|
RedirectedPath := '';
|
||||||
|
|
||||||
if (ExpandedPath <> '') and ((DesiredAccess and WinNative.DELETE) = 0) and (CreateDisposition = WinNative.FILE_OPEN) then begin
|
if (ExpandedPath <> '') and ((DesiredAccess and WinNative.DELETE) = 0) and (CreateDisposition = WinNative.FILE_OPEN) then begin
|
||||||
RedirectedPath := VfsBase.GetVfsItemRealPath(StrLib.ExcludeTrailingDelimW(ExpandedPath, @HadTrailingDelim), @FileInfo);
|
RedirectedPath := VfsBase.GetVfsItemRealPath(StrLib.ExcludeTrailingDelimW(ExpandedPath, @HadTrailingDelim));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if RedirectedPath = '' then begin
|
if RedirectedPath = '' then begin
|
||||||
@ -231,25 +236,33 @@ begin
|
|||||||
RedirectedPath := RedirectedPath + '\';
|
RedirectedPath := RedirectedPath + '\';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (RedirectedPath <> '') and (RedirectedPath[1] <> '\') then begin
|
if RedirectedPath <> '' then begin
|
||||||
RedirectedPath := '\??\' + RedirectedPath;
|
if RedirectedPath[1] <> '\' then begin
|
||||||
|
RedirectedPath := '\??\' + RedirectedPath;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ReplacedObjAttrs.RootDirectory := 0;
|
||||||
|
ReplacedObjAttrs.Attributes := ReplacedObjAttrs.Attributes or WinNative.OBJ_CASE_INSENSITIVE;
|
||||||
|
ReplacedObjAttrs.ObjectName.AssignExistingStr(RedirectedPath);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ReplacedObjAttrs.RootDirectory := 0;
|
with VfsOpenFiles.OpenFilesCritSection do begin
|
||||||
ReplacedObjAttrs.Attributes := ReplacedObjAttrs.Attributes or WinNative.OBJ_CASE_INSENSITIVE;
|
Enter;
|
||||||
ReplacedObjAttrs.ObjectName.AssignExistingStr(RedirectedPath);
|
|
||||||
|
|
||||||
result := OrigFunc(FileHandle, DesiredAccess, @ReplacedObjAttrs, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);
|
result := OrigFunc(FileHandle, DesiredAccess, @ReplacedObjAttrs, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);
|
||||||
|
|
||||||
if (result = WinNative.STATUS_SUCCESS) and Utils.HasFlag(WinNative.FILE_SYNCHRONOUS_IO_NONALERT, CreateOptions) and Utils.HasFlag(WinNative.SYNCHRONIZE, DesiredAccess) then begin
|
if (result = WinNative.STATUS_SUCCESS) and (ExpandedPath <> '') then begin
|
||||||
VfsOpenFiles.SetOpenedFileInfo(FileHandle^, TOpenedFile.Create(FileHandle^, ExpandedPath));
|
VfsOpenFiles.SetOpenedFileInfo(FileHandle^, TOpenedFile.Create(FileHandle^, ExpandedPath));
|
||||||
|
end;
|
||||||
|
|
||||||
|
Leave;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if VfsDebug.LoggingEnabled then begin
|
if VfsDebug.LoggingEnabled then begin
|
||||||
if ExpandedPath <> StripNtAbsPathPrefix(RedirectedPath) then begin
|
if ExpandedPath <> StripNtAbsPathPrefix(RedirectedPath) then begin
|
||||||
WriteLog('NtCreateFile', Format('Access: 0x%x. Handle: %x. Status: %x. Redirected "%s" => "%s"', [DesiredAccess, FileHandle^, result, StrLib.WideToAnsiSubstitute(ExpandedPath), StrLib.WideToAnsiSubstitute(StripNtAbsPathPrefix(RedirectedPath))]));
|
WriteLog('[LEAVE] NtCreateFile', Format('Handle: %x. Status: %x.'#13#10'Expanded: "%s"'#13#10'Redirected: "%s"', [FileHandle^, result, ExpandedPath, StripNtAbsPathPrefix(RedirectedPath)]));
|
||||||
end else begin
|
end else begin
|
||||||
WriteLog('NtCreateFile', Format('Access: 0x%x. Handle: %x. Status: %x. Path: "%s"', [DesiredAccess, FileHandle^, result, StrLib.WideToAnsiSubstitute(ExpandedPath)]));
|
WriteLog('[LEAVE] NtCreateFile', Format('Handle: %x. Status: %x.'#13#10'Expanded: "%s"', [FileHandle^, result, ExpandedPath]));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end; // .function Hook_NtCreateFile
|
end; // .function Hook_NtCreateFile
|
||||||
@ -257,11 +270,12 @@ end; // .function Hook_NtCreateFile
|
|||||||
function Hook_NtClose (OrigFunc: WinNative.TNtClose; hData: HANDLE): NTSTATUS; stdcall;
|
function Hook_NtClose (OrigFunc: WinNative.TNtClose; hData: HANDLE): NTSTATUS; stdcall;
|
||||||
begin
|
begin
|
||||||
if VfsDebug.LoggingEnabled then begin
|
if VfsDebug.LoggingEnabled then begin
|
||||||
WriteLog('NtClose', Format('Handle: %x', [integer(hData)]));
|
WriteLog('[ENTER] NtClose', Format('Handle: %x', [integer(hData)]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
with OpenFilesCritSection do begin
|
with VfsOpenFiles.OpenFilesCritSection do begin
|
||||||
Enter;
|
Enter;
|
||||||
|
|
||||||
result := OrigFunc(hData);
|
result := OrigFunc(hData);
|
||||||
|
|
||||||
if WinNative.NT_SUCCESS(result) then begin
|
if WinNative.NT_SUCCESS(result) then begin
|
||||||
@ -272,7 +286,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
if VfsDebug.LoggingEnabled then begin
|
if VfsDebug.LoggingEnabled then begin
|
||||||
WriteLog('NtClose', Format('Status: %x', [integer(result)]));
|
WriteLog('[LEAVE] NtClose', Format('Status: %x', [integer(result)]));
|
||||||
end;
|
end;
|
||||||
end; // .function Hook_NtClose
|
end; // .function Hook_NtClose
|
||||||
|
|
||||||
@ -526,36 +540,41 @@ begin
|
|||||||
NativeNtQueryAttributesFile := VfsPatching.SpliceWinApi
|
NativeNtQueryAttributesFile := VfsPatching.SpliceWinApi
|
||||||
(
|
(
|
||||||
VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtQueryAttributesFile'),
|
VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtQueryAttributesFile'),
|
||||||
@Hook_NtQueryAttributesFile
|
@Hook_NtQueryAttributesFile,
|
||||||
|
@NtQueryAttributesFilePatch
|
||||||
);
|
);
|
||||||
|
|
||||||
WriteLog('InstallHook', 'Installing NtQueryFullAttributesFile hook');
|
WriteLog('InstallHook', 'Installing NtQueryFullAttributesFile hook');
|
||||||
NativeNtQueryFullAttributesFile := VfsPatching.SpliceWinApi
|
NativeNtQueryFullAttributesFile := VfsPatching.SpliceWinApi
|
||||||
(
|
(
|
||||||
VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtQueryFullAttributesFile'),
|
VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtQueryFullAttributesFile'),
|
||||||
@Hook_NtQueryFullAttributesFile
|
@Hook_NtQueryFullAttributesFile,
|
||||||
|
@NtQueryFullAttributesFilePatch
|
||||||
);
|
);
|
||||||
|
|
||||||
// WriteLog('InstallHook', 'Installing NtOpenFile hook');
|
WriteLog('InstallHook', 'Installing NtOpenFile hook');
|
||||||
// NativeNtOpenFile := VfsPatching.SpliceWinApi
|
NativeNtOpenFile := VfsPatching.SpliceWinApi
|
||||||
// (
|
(
|
||||||
// VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtOpenFile'),
|
VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtOpenFile'),
|
||||||
// @Hook_NtOpenFile
|
@Hook_NtOpenFile,
|
||||||
// );
|
@NtOpenFilePatch
|
||||||
|
);
|
||||||
|
|
||||||
// WriteLog('InstallHook', 'Installing NtCreateFile hook');
|
WriteLog('InstallHook', 'Installing NtCreateFile hook');
|
||||||
// NativeNtCreateFile := VfsPatching.SpliceWinApi
|
NativeNtCreateFile := VfsPatching.SpliceWinApi
|
||||||
// (
|
(
|
||||||
// VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtCreateFile'),
|
VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtCreateFile'),
|
||||||
// @Hook_NtCreateFile
|
@Hook_NtCreateFile,
|
||||||
// );
|
@NtCreateFilePatch
|
||||||
|
);
|
||||||
|
|
||||||
// WriteLog('InstallHook', 'Installing NtClose hook');
|
WriteLog('InstallHook', 'Installing NtClose hook');
|
||||||
// NativeNtClose := VfsPatching.SpliceWinApi
|
NativeNtClose := VfsPatching.SpliceWinApi
|
||||||
// (
|
(
|
||||||
// VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtClose'),
|
VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtClose'),
|
||||||
// @Hook_NtClose
|
@Hook_NtClose,
|
||||||
// );
|
@NtClosePatch
|
||||||
|
);
|
||||||
|
|
||||||
// WriteLog('InstallHook', 'Installing NtQueryDirectoryFile hook');
|
// WriteLog('InstallHook', 'Installing NtQueryDirectoryFile hook');
|
||||||
// NativeNtQueryDirectoryFile := VfsPatching.SpliceWinApi
|
// NativeNtQueryDirectoryFile := VfsPatching.SpliceWinApi
|
||||||
@ -569,6 +588,28 @@ begin
|
|||||||
end; // .with
|
end; // .with
|
||||||
end; // .procedure InstallHooks
|
end; // .procedure InstallHooks
|
||||||
|
|
||||||
|
procedure UninstallHooks;
|
||||||
begin
|
begin
|
||||||
|
with HooksCritSection do begin
|
||||||
|
Enter;
|
||||||
|
|
||||||
|
NtQueryAttributesFilePatch.Rollback;
|
||||||
|
NtQueryFullAttributesFilePatch.Rollback;
|
||||||
|
NtOpenFilePatch.Rollback;
|
||||||
|
NtCreateFilePatch.Rollback;
|
||||||
|
NtClosePatch.Rollback;
|
||||||
|
|
||||||
|
Leave;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
HooksCritSection.Init;
|
HooksCritSection.Init;
|
||||||
|
finalization
|
||||||
|
with VfsBase.VfsCritSection do begin
|
||||||
|
Enter;
|
||||||
|
VfsBase.ResetVfs;
|
||||||
|
UninstallHooks;
|
||||||
|
Leave;
|
||||||
|
end;
|
||||||
end.
|
end.
|
||||||
@ -4,17 +4,24 @@ unit VfsPatching;
|
|||||||
All hooks are thread-safe.
|
All hooks are thread-safe.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
|
||||||
(***) interface (***)
|
(***) interface (***)
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Windows, SysUtils, Utils, PatchForge;
|
Windows, SysUtils, Utils, PatchForge;
|
||||||
|
|
||||||
|
type
|
||||||
|
PAppliedPatch = ^TAppliedPatch;
|
||||||
|
TAppliedPatch = record
|
||||||
|
Addr: pointer;
|
||||||
|
Bytes: Utils.TArrayOfByte;
|
||||||
|
|
||||||
|
procedure Rollback;
|
||||||
|
end;
|
||||||
|
|
||||||
(* Replaces original STDCALL function with the new one with the same prototype and one extra argument.
|
(* Replaces original STDCALL function with the new one with the same prototype and one extra argument.
|
||||||
The argument is callable pointer, used to execute original function. The pointer is passed as THE FIRST
|
The argument is callable pointer, used to execute original function. The pointer is passed as THE FIRST
|
||||||
argument before other arguments. *)
|
argument before other arguments. *)
|
||||||
function SpliceWinApi (OrigFunc, HandlerFunc: pointer): pointer;
|
function SpliceWinApi (OrigFunc, HandlerFunc: pointer; {n} AppliedPatch: PAppliedPatch = nil): pointer;
|
||||||
|
|
||||||
|
|
||||||
(***) implementation (***)
|
(***) implementation (***)
|
||||||
@ -68,7 +75,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end; // .function WritePatchAtCode
|
end; // .function WritePatchAtCode
|
||||||
|
|
||||||
function SpliceWinApi (OrigFunc, HandlerFunc: pointer): pointer;
|
function SpliceWinApi (OrigFunc, HandlerFunc: pointer; {n} AppliedPatch: PAppliedPatch = nil): pointer;
|
||||||
const
|
const
|
||||||
CODE_ADDR_ALIGNMENT = 8;
|
CODE_ADDR_ALIGNMENT = 8;
|
||||||
|
|
||||||
@ -121,9 +128,23 @@ begin
|
|||||||
// Create and apply hook at target function start
|
// Create and apply hook at target function start
|
||||||
p.Clear();
|
p.Clear();
|
||||||
p.Jump(PatchForge.JMP, SpliceBridge);
|
p.Jump(PatchForge.JMP, SpliceBridge);
|
||||||
|
|
||||||
|
if AppliedPatch <> nil then begin
|
||||||
|
AppliedPatch.Addr := OrigFunc;
|
||||||
|
SetLength(AppliedPatch.Bytes, p.Size);
|
||||||
|
Utils.CopyMem(p.Size, OrigFunc, @AppliedPatch.Bytes[0]);
|
||||||
|
end;
|
||||||
|
|
||||||
WritePatchAtCode(p.PatchMaker, OrigFunc);
|
WritePatchAtCode(p.PatchMaker, OrigFunc);
|
||||||
// * * * * * //
|
// * * * * * //
|
||||||
p.Release;
|
p.Release;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TAppliedPatch.Rollback;
|
||||||
|
begin
|
||||||
|
if Self.Bytes <> nil then begin
|
||||||
|
WriteAtCode(Length(Self.Bytes), @Self.Bytes[0], Self.Addr);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
@ -5,6 +5,10 @@ Move copyright to single file license?
|
|||||||
SetCurrentDirectoryW(GetCurrentDirectoryW)
|
SetCurrentDirectoryW(GetCurrentDirectoryW)
|
||||||
System.IsMultiThread for DLL and exported API
|
System.IsMultiThread for DLL and exported API
|
||||||
|
|
||||||
|
In order to prevent crashing on application exit we can disable logging to console
|
||||||
|
in VFS in ExitProcess, RtlTerminateProcess or LdrShutdownProcess.
|
||||||
|
But maybe source of crashes lies somewhere else.
|
||||||
|
|
||||||
(* Trying to turn off DEP *)
|
(* Trying to turn off DEP *)
|
||||||
SetProcessDEPPolicyAddr := Windows.GetProcAddress(Kernel32Handle, 'SetProcessDEPPolicy');
|
SetProcessDEPPolicyAddr := Windows.GetProcAddress(Kernel32Handle, 'SetProcessDEPPolicy');
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user