From 360fddaa462c02e54d513c869cd4608052c50869 Mon Sep 17 00:00:00 2001 From: Berserker Date: Sat, 4 May 2019 22:39:26 +0300 Subject: [PATCH] Added support for NtQueryFullAttributesFile --- Tests/VfsIntegratedTest.pas | 27 ++++++++++++++- VfsHooks.pas | 66 +++++++++++++++++++++++-------------- _TODO_.txt | 2 ++ 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/Tests/VfsIntegratedTest.pas b/Tests/VfsIntegratedTest.pas index 6622082..5dfac2b 100644 --- a/Tests/VfsIntegratedTest.pas +++ b/Tests/VfsIntegratedTest.pas @@ -21,6 +21,7 @@ type published procedure TestGetFileAttributes; + procedure TestGetFileAttributesEx; end; (***) implementation (***) @@ -90,7 +91,31 @@ begin Check(HasValidAttrs(RootDir + '\503.html', 0, Windows.FILE_ATTRIBUTE_DIRECTORY), '{3}'); Check(HasValidAttrs(RootDir + '\Hobbots\', Windows.FILE_ATTRIBUTE_DIRECTORY), '{4}'); Check(HasValidAttrs(RootDir + '\Mods', Windows.FILE_ATTRIBUTE_DIRECTORY), '{5}'); -end; +end; // .procedure TestIntegrated.TestGetFileAttributes; + +procedure TestIntegrated.TestGetFileAttributesEx; +var + RootDir: string; + + function GetFileSize (const Path: string): integer; + var + FileData: Windows.TWin32FileAttributeData; + + begin + result := -1; + + if Windows.GetFileAttributesExA(pchar(Path), Windows.GetFileExInfoStandard, @FileData) then begin + result := Int(FileData.nFileSizeLow); + end; + end; + +begin + RootDir := Self.GetRootDir; + CheckEquals(-1, GetFileSize(RootDir + '\non-existing.non'), '{1}'); + CheckEquals(47, GetFileSize(RootDir + '\Hobbots\mms.cfg'), '{2}'); + CheckEquals(22, GetFileSize(RootDir + '\503.html'), '{3}'); + CheckEquals(318, GetFileSize(RootDir + '\default'), '{4}'); +end; // .procedure TestIntegrated.TestGetFileAttributesEx; begin RegisterTest(TestIntegrated.Suite); diff --git a/VfsHooks.pas b/VfsHooks.pas index 4914629..0de1268 100644 --- a/VfsHooks.pas +++ b/VfsHooks.pas @@ -84,7 +84,7 @@ var begin if VfsDebug.LoggingEnabled then begin - WriteLog('NtQueryAttributesFile', Format('Dir: %d. Path: "%s"', [ObjectAttributes.RootDirectory, ObjectAttributes.ObjectName.ToWideStr()])); + WriteLog('[ENTER] NtQueryAttributesFile', Format('Dir: %d.'#13#10'Path: "%s"', [ObjectAttributes.RootDirectory, ObjectAttributes.ObjectName.ToWideStr()])); end; ReplacedObjAttrs := ObjectAttributes^; @@ -127,7 +127,7 @@ begin end; // .else if VfsDebug.LoggingEnabled then begin - WriteLog('NtQueryAttributesFile', Format('Result: %x. Attrs: 0x%x. Path: "%s" => "%s"', [result, FileInformation.FileAttributes, string(ExpandedPath), string(RedirectedPath)])); + WriteLog('[LEAVE] NtQueryAttributesFile', Format('Result: %x. Attrs: 0x%x.'#13#10'Expanded: "%s"'#13#10'Redirected: "%s"', [result, FileInformation.FileAttributes, string(ExpandedPath), string(RedirectedPath)])); end; end; // .function Hook_NtQueryAttributesFile @@ -136,11 +136,12 @@ var ExpandedPath: WideString; RedirectedPath: WideString; ReplacedObjAttrs: WinNative.TObjectAttributes; + FileInfo: TNativeFileInfo; HadTrailingDelim: boolean; begin if VfsDebug.LoggingEnabled then begin - WriteLog('NtQueryFullAttributesFile', Format('Dir: %d. Path: "%s"', [ObjectAttributes.RootDirectory, ObjectAttributes.ObjectName.ToWideStr()])); + WriteLog('[ENTER] NtQueryFullAttributesFile', Format('Dir: %d.'#13#10'Path: "%s"', [ObjectAttributes.RootDirectory, ObjectAttributes.ObjectName.ToWideStr()])); end; ReplacedObjAttrs := ObjectAttributes^; @@ -149,27 +150,44 @@ begin RedirectedPath := ''; if ExpandedPath <> '' then begin - RedirectedPath := VfsBase.GetVfsItemRealPath(StrLib.ExcludeTrailingDelimW(ExpandedPath, @HadTrailingDelim)); + RedirectedPath := VfsBase.GetVfsItemRealPath(StrLib.ExcludeTrailingDelimW(ExpandedPath, @HadTrailingDelim), @FileInfo); end; - if RedirectedPath = '' then begin + // Return cached VFS file info + if RedirectedPath <> '' then begin + if not HadTrailingDelim or Utils.HasFlag(FILE_ATTRIBUTE_DIRECTORY, FileInfo.Base.FileAttributes) then begin + FileInformation.CreationTime := FileInfo.Base.CreationTime; + FileInformation.LastAccessTime := FileInfo.Base.LastAccessTime; + FileInformation.LastWriteTime := FileInfo.Base.LastWriteTime; + FileInformation.ChangeTime := FileInfo.Base.ChangeTime; + FileInformation.AllocationSize := FileInfo.Base.AllocationSize; + FileInformation.EndOfFile := FileInfo.Base.EndOfFile; + FileInformation.FileAttributes := FileInfo.Base.FileAttributes; + FileInformation.Reserved := 0; + result := WinNative.STATUS_SUCCESS; + end else begin + result := WinNative.STATUS_NO_SUCH_FILE; + end; + end + // Query file with real path + else begin RedirectedPath := ExpandedPath; - end else if HadTrailingDelim then begin - RedirectedPath := RedirectedPath + '\'; - end; - - if (RedirectedPath <> '') and (RedirectedPath[1] <> '\') then begin - RedirectedPath := '\??\' + RedirectedPath; - end; - ReplacedObjAttrs.RootDirectory := 0; - ReplacedObjAttrs.Attributes := ReplacedObjAttrs.Attributes or WinNative.OBJ_CASE_INSENSITIVE; - ReplacedObjAttrs.ObjectName.AssignExistingStr(RedirectedPath); - - result := OrigFunc(@ReplacedObjAttrs, FileInformation); + if RedirectedPath <> '' then begin + 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; + + result := OrigFunc(@ReplacedObjAttrs, FileInformation); + end; // .else if VfsDebug.LoggingEnabled then begin - WriteLog('NtQueryFullAttributesFile', Format('Result: %x. Attrs: 0x%x. Path: "%s" => "%s"', [result, FileInformation.FileAttributes, string(ExpandedPath), string(RedirectedPath)])); + WriteLog('[LEAVE] NtQueryFullAttributesFile', Format('Result: %x. Attrs: 0x%x.'#13#10'Expanded: "%s"'#13#10'Redirected: "%s"', [result, FileInformation.FileAttributes, string(ExpandedPath), string(RedirectedPath)])); end; end; // .Hook_NtQueryFullAttributesFile @@ -511,12 +529,12 @@ begin @Hook_NtQueryAttributesFile ); - // WriteLog('InstallHook', 'Installing NtQueryFullAttributesFile hook'); - // NativeNtQueryFullAttributesFile := VfsPatching.SpliceWinApi - // ( - // VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtQueryFullAttributesFile'), - // @Hook_NtQueryFullAttributesFile - // ); + WriteLog('InstallHook', 'Installing NtQueryFullAttributesFile hook'); + NativeNtQueryFullAttributesFile := VfsPatching.SpliceWinApi + ( + VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtQueryFullAttributesFile'), + @Hook_NtQueryFullAttributesFile + ); // WriteLog('InstallHook', 'Installing NtOpenFile hook'); // NativeNtOpenFile := VfsPatching.SpliceWinApi diff --git a/_TODO_.txt b/_TODO_.txt index ebb4d42..32d7a87 100644 --- a/_TODO_.txt +++ b/_TODO_.txt @@ -1,5 +1,7 @@ UTF-8 Logging +Move copyright to single file license? + SetCurrentDirectoryW(GetCurrentDirectoryW) System.IsMultiThread for DLL and exported API