Search code examples
c#winapiiopinvokentfs

How to get a NTFS file id for a folder


How to get a unique NTFS file id for a folder in c# ?


Solution

  •     internal static Int64 GetDirectoryId(string dir)
        {
            var handle = CreateFile(dir, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, 0x02000000 | 0x00000080, IntPtr.Zero);
            var fileStruct = new FILE_ID_BOTH_DIR_INFO();
            GetFileInformationByHandleEx(handle, FILE_INFO_BY_HANDLE_CLASS.FileIdBothDirectoryInfo, out fileStruct, (uint)Marshal.SizeOf(fileStruct));
            CloseHandle(handle);
            var win32Error = Marshal.GetLastWin32Error();
            if (win32Error != 0)
                throw new Win32Exception();
    
            return fileStruct.FileId.QuadPart;
        }
    
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool GetFileInformationByHandleEx(
            IntPtr hFile,
            FILE_INFO_BY_HANDLE_CLASS infoClass,
            out FILE_ID_BOTH_DIR_INFO dirInfo,
            uint dwBufferSize);
    
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr CloseHandle(
            IntPtr handle);
    
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr CreateFile(
            string lpFileName,
            [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
            [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
            IntPtr lpSecurityAttributes,
            [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
            uint dwFlagsAndAttributes,
            IntPtr hTemplateFile);
    
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        private struct FILE_ID_BOTH_DIR_INFO
        {
            public uint NextEntryOffset;
            public uint FileIndex;
            public LARGE_INTEGER CreationTime;
            public LARGE_INTEGER LastAccessTime;
            public LARGE_INTEGER LastWriteTime;
            public LARGE_INTEGER ChangeTime;
            public LARGE_INTEGER EndOfFile;
            public LARGE_INTEGER AllocationSize;
            public uint FileAttributes;
            public uint FileNameLength;
            public uint EaSize;
            public char ShortNameLength;
            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 12)]
            public string ShortName;
            public LARGE_INTEGER FileId;
            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 1)]
            public string FileName;
        }
    
        [StructLayout(LayoutKind.Explicit, Size=8)]
        private struct LARGE_INTEGER
        {
            [FieldOffset(0)]public Int64 QuadPart;
            [FieldOffset(0)]public UInt32 LowPart;
            [FieldOffset(4)]public Int32 HighPart;
        }
    
        private enum FILE_INFO_BY_HANDLE_CLASS
        {
            FileIdBothDirectoryInfo = 10
        }