diff --git a/src/Meziantou.Framework.Win32.ChangeJournal/FileIdentifier.cs b/src/Meziantou.Framework.Win32.ChangeJournal/FileIdentifier.cs index 362bee30..e52149c8 100644 --- a/src/Meziantou.Framework.Win32.ChangeJournal/FileIdentifier.cs +++ b/src/Meziantou.Framework.Win32.ChangeJournal/FileIdentifier.cs @@ -1,6 +1,10 @@ -using System.Globalization; +using System.ComponentModel; +using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using Microsoft.Win32.SafeHandles; +using Windows.Win32; using Windows.Win32.Storage.FileSystem; namespace Meziantou.Framework.Win32; @@ -28,6 +32,26 @@ internal FileIdentifier(FILE_ID_128 parentFileReferenceNumber) { } + [SupportedOSPlatform("windows6.0.6000")] + public unsafe static FileIdentifier FromFile(string path) + { + using var handle = File.OpenHandle(path); + return FromFile(handle); + } + + [SupportedOSPlatform("windows6.0.6000")] + public unsafe static FileIdentifier FromFile(SafeFileHandle handle) + { + var result = new FILE_ID_INFO(); + var pointer = Unsafe.AsPointer(ref result); + if (PInvoke.GetFileInformationByHandleEx(handle, FILE_INFO_BY_HANDLE_CLASS.FileIdInfo, pointer, (uint)sizeof(FILE_ID_INFO))) + { + return new FileIdentifier(result.FileId); + } + + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + public bool Equals(FileIdentifier other) => _value == other._value; public override bool Equals([NotNullWhen(true)] object? obj) => obj is FileIdentifier identifier && Equals(identifier); public override int GetHashCode() => _value.GetHashCode(); diff --git a/src/Meziantou.Framework.Win32.ChangeJournal/Meziantou.Framework.Win32.ChangeJournal.csproj b/src/Meziantou.Framework.Win32.ChangeJournal/Meziantou.Framework.Win32.ChangeJournal.csproj index a3945fec..c42bbc6e 100644 --- a/src/Meziantou.Framework.Win32.ChangeJournal/Meziantou.Framework.Win32.ChangeJournal.csproj +++ b/src/Meziantou.Framework.Win32.ChangeJournal/Meziantou.Framework.Win32.ChangeJournal.csproj @@ -4,7 +4,7 @@ $(LatestTargetFrameworks) false Meziantou.Framework.Win32 - 3.0.0 + 3.1.0 Allow to access the Windows Change Journal to quickly detect changed files diff --git a/src/Meziantou.Framework.Win32.ChangeJournal/NativeMethods.txt b/src/Meziantou.Framework.Win32.ChangeJournal/NativeMethods.txt index 376efc23..509ada48 100644 --- a/src/Meziantou.Framework.Win32.ChangeJournal/NativeMethods.txt +++ b/src/Meziantou.Framework.Win32.ChangeJournal/NativeMethods.txt @@ -11,4 +11,6 @@ Windows.Win32.System.Ioctl.USN_RECORD_V2 Windows.Win32.System.Ioctl.USN_RECORD_V3 Windows.Win32.System.Ioctl.USN_RECORD_V4 Windows.Win32.System.Ioctl.USN_TRACK_MODIFIED_RANGES -FLAG_USN_TRACK_MODIFIED_RANGES_ENABLE \ No newline at end of file +FLAG_USN_TRACK_MODIFIED_RANGES_ENABLE +GetFileInformationByHandleEx +FILE_ID_INFO \ No newline at end of file diff --git a/tests/Meziantou.Framework.Win32.ChangeJournal.Tests/ChangeJournalTests.cs b/tests/Meziantou.Framework.Win32.ChangeJournal.Tests/ChangeJournalTests.cs index 4124e8e5..90d19449 100644 --- a/tests/Meziantou.Framework.Win32.ChangeJournal.Tests/ChangeJournalTests.cs +++ b/tests/Meziantou.Framework.Win32.ChangeJournal.Tests/ChangeJournalTests.cs @@ -75,6 +75,14 @@ public void NonAdministrator() }); } + [RunIfFact(FactOperatingSystem.Windows)] + public void GetFileIdentifier() + { + var file = Path.GetTempFileName(); + var identifier = FileIdentifier.FromFile(file); + Assert.NotEqual(default, identifier); + } + [Fact] public void FileIdentifier128ToString() {