1

I just read this post HERE and wondered if it is possible to get a current file path from that ID.

So if a file gets moved can I get the new file path by searching for that ID? Unfortunately I couldn't find anything about this topic.

Or is the ID only used to identify a file and can't be used to track the location ?

Thanks in advance.

// Added Code

public class WinAPI
{
    [DllImport("ntdll.dll", SetLastError = true)]
    public static extern IntPtr NtQueryInformationFile(IntPtr fileHandle, ref IO_STATUS_BLOCK IoStatusBlock, IntPtr pInfoBlock, uint length, FILE_INFORMATION_CLASS fileInformation);

    public struct IO_STATUS_BLOCK
    {
        uint status;
        ulong information;
    }
    public struct _FILE_INTERNAL_INFORMATION
    {
        public ulong IndexNumber;
    }

    // Abbreviated, there are more values than shown
    public enum FILE_INFORMATION_CLASS
    {
        FileDirectoryInformation = 1,     // 1
        FileFullDirectoryInformation,     // 2
        FileBothDirectoryInformation,     // 3
        FileBasicInformation,         // 4
        FileStandardInformation,      // 5
        FileInternalInformation      // 6
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool GetFileInformationByHandle(IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr OpenFileById(IntPtr hFile, FILE_ID_DESCRIPTOR lpFileID, uint dwDesiredAccess, uint dwShareMode, uint dwFlagas);

    [StructLayout(LayoutKind.Explicit)]
    public struct FILE_ID_DESCRIPTOR
    {
        [FieldOffset(0)] public uint dwSize;
        [FieldOffset(4)] public FILE_ID_TYPE type;
       // [FieldOffset(8)] public Guid guid;
        [FieldOffset(8)] public long FileReferenceNumber;
    }

    public enum FILE_ID_TYPE
    {
        FileIdType = 0,
        ObjectIdType = 1,
        ExtendedFileIdType = 2,
        MaximumFileIdType
    };

    public struct BY_HANDLE_FILE_INFORMATION
    {
        public uint FileAttributes;
        public FILETIME CreationTime;
        public FILETIME LastAccessTime;
        public FILETIME LastWriteTime;
        public uint VolumeSerialNumber;
        public uint FileSizeHigh;
        public uint FileSizeLow;
        public uint NumberOfLinks;
        public uint FileIndexHigh;
        public uint FileIndexLow;
    }
}

public class File_Handle
{

    public ulong Get_Index()
    {
        WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo = new WinAPI.BY_HANDLE_FILE_INFORMATION();

        FileInfo fi = new FileInfo(@"D:\Test\Testfile.txt");
        FileStream fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

        WinAPI.GetFileInformationByHandle(fs.Handle, out objectFileInfo);

        fs.Close();

        ulong fileIndex = ((ulong)objectFileInfo.FileIndexHigh << 32) + (ulong)objectFileInfo.FileIndexLow;

        return fileIndex;
    }

    public string Retrieve_File(ulong Index)
    {
        // WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo = new WinAPI.BY_HANDLE_FILE_INFORMATION();
        // WinAPI.FILE_ID_DESCRIPTOR Descriptor = new WinAPI.FILE_ID_DESCRIPTOR { dwSize = sizeof(uint) + sizeof(WinAPI.FILE_ID_TYPE) + sizeof(long), type = WinAPI.FILE_ID_TYPE.FileIdType, FileReferenceNumber = (long)Index };
        WinAPI.FILE_ID_DESCRIPTOR Descriptor = new WinAPI.FILE_ID_DESCRIPTOR { dwSize = 100, type = WinAPI.FILE_ID_TYPE.FileIdType, FileReferenceNumber = (long)Index };

        FileInfo fi = new FileInfo(@"D:\Test\TestfileRef.txt");
        FileStream fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

        //FileStream wf = new FileStream(WinAPI.OpenFileById(fs.Handle, Descriptor, 0, 4, 0x08000000), FileAccess.ReadWrite);
        FileStream wf = new FileStream(WinAPI.OpenFileById(fs.Handle, Descriptor, 0, 0, 0x08000000), FileAccess.ReadWrite);

        WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo = new WinAPI.BY_HANDLE_FILE_INFORMATION();
        WinAPI.GetFileInformationByHandle(wf.Handle, out objectFileInfo);
        fs.Close();

        wf.Close();

        return "Dummy";

    }
}
Community
  • 1
  • 1
B. Ueno
  • 159
  • 2
  • 13

1 Answers1

0

Because of hardlinks, a file can have more than one path. The File Id is only guaranteed to be stable as long as somebody has a open handle on the file but they are always stable on NTFS in practice. Defragmentation can change the Id on FAT32.

You could try GetFileInformationByHandleEx but results may vary based on the Windows version and file system.

Anders
  • 97,548
  • 12
  • 110
  • 164
  • Thanks for your fast response, but if I only know the file index, I dont have a handle. I also found this function, but I don't know how to create a hande from the file index. – B. Ueno Apr 28 '17 at 12:24
  • Use OpenFileById. – Anders Apr 28 '17 at 13:07
  • Okay I tried to use the OpenFileById method but I am having some trouble here. I've created the Enum for the FILE_ID_TYPE and the struct FILE_ID_DESCRIPTOR. But to use the function I need the descriptor, but I don't know where to get it so I tried to create it by myself. But I guess I messed up the dwSize because I get an "Access Violation Exception". Could you help me again with this ? – B. Ueno Apr 28 '17 at 14:56
  • Yes you create/initialize it yourself. Did you set the size to 24? Is the struct large enough? – Anders Apr 28 '17 at 15:18
  • I just varied the size a bit but the problem still occures. Let me just repeat how I understood that method. "fFile" is a handle to a random file on the volume I have my target file on (the one I have the index from), The descriptor is used to determine what I want to do. In this case I have the FileIndex which is also stored in the descriptor. I could also imagine that I messed up the "dwDesiredAccess", "dwSharedMode" or "dwFlagas". My current setup is 0,4, & 0x08000000. Any Ideas ? – B. Ueno Apr 28 '17 at 15:38
  • Set flags to 0. If it crashes with access violation then the descriptor is too small/invalid or the pointer to it is wrong. – Anders Apr 28 '17 at 16:15
  • I included the code I reused and the function "Retrieve_File" I've written. Can you may check if its all garbage or only some mistakes ? – B. Ueno Apr 28 '17 at 19:49
  • You need the GUID member and the struct needs to be exactly 24 bytes and so does dwSize. – Anders Apr 28 '17 at 22:09
  • But according to the WIN-API it is an union and can be the GUID or a LONG INTEGER (As described here in 2nd comment http://stackoverflow.com/questions/24724343/get-file-info-from-ntfs-mft-reference-number). Maybe the file index i pass to the retrieve function is wrong ? – B. Ueno Apr 29 '17 at 08:02
  • Call GetFileInformationByHandle on a open handle so you know the id you get is valid. The union should be the correct size so you must include its largest member, the guid. Maybe ask a new question if you cannot figure this out. – Anders Apr 29 '17 at 10:21