是否有用于将文件ID和卷序列转换为唯一路径的Windows API?

时间:2014-12-16 22:01:00

标签: c++ windows winapi

背景:我知道在Windows中,无法同时安装两个具有相同序列的卷。此外,在具有相同文件ID的单个安装卷中不能存在两个文件。编辑:可能不是这样。然后,给定任何卷句柄或驱动器号,file_id映射到唯一的文件路径。是否有可以为任何卷执行此操作的Windows API?

进展:这里有多远:

#import <Windows.h>
...
    FILE_ID_DESCRIPTOR file_id;
    file_id.dwSize = 24;
    file_id.Type = FileIdType;
    file_id.QuadPart = /* file reference number */;
...
BOOL File::open(HANDLE *volume) {
    file = OpenFileById(*volume, &file_id, SYNCHRONIZE | FILE_READ_ATTRIBUTES
                        | READ_CONTROL | ACCESS_SYSTEM_SECURITY,
                        SHARE_MODE, NULL, OPEN_FLAGS);
    if (file == INVALID_HANDLE_VALUE) {
        if (GetLastError() == 1314UL) { /* SACL permissions denied */
            file = OpenFileById(*volume, &file_id, SYNCHRONIZE | FILE_READ_ATTRIBUTES
                                | READ_CONTROL, SHARE_MODE, NULL, OPEN_FLAGS);
            perms = 0x4 | 0x2 | 0x1;
        }
        if (GetLastError() == 5UL) { /* Security permissions denied */
            file = OpenFileById(*volume, &file_id, SYNCHRONIZE | FILE_READ_ATTRIBUTES,
                                SHARE_MODE, NULL, OPEN_FLAGS);
            perms = 0x2 | 0x1;
        }
        if (file == INVALID_HANDLE_VALUE) { /* All permissions denied */
            file = OpenFileById(*volume, &file_id, SYNCHRONIZE,
                                SHARE_MODE, NULL, OPEN_FLAGS);
            perms = 0x1;
        }
        if (file == INVALID_HANDLE_VALUE) /* File name denied|file doesn't exist */
            perms = 0;
    } else {
        perms = 0x8 | 0x4 | 0x2 | 0x1;
    }
    return file != INVALID_HANDLE_VALUE;
}
...
    if (perms) {
        path = new WCHAR[260]; /* expected file length */
        l = GetFinalPathNameByHandle(file, path, 260, 0);
        if (l >= 260) {
            delete[] path;
            path = new WCHAR[l];
            GetFinalPathNameByHandle(file, path, l, 0);
        } else if (l <= 0) {
            delete[] path;
            path = NULL;
        }
    }

在代码的第一部分中,我使用已经打开的卷的句柄打开文件的句柄,这对于已安装的驱动器号很容易。 file是我即将打开的文件的句柄。 在第二部分中,我使用句柄获取全名,包括DOS样式的驱动器名称(例如,C:\Users\rmanne\Downloads\test.txt)。只要perms非零,我就可以保证在代码的第二部分中有一个人类可读的绝对路径。但是,我只用NTFS进行了测试。根据API,它也可以与CsvFS和ReFS一起使用,但我还没有机会用这些来测试它。

这里提供了两个功能:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa364962%28v=vs.85%29.aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365432%28v=vs.85%29.aspx

正如您所看到的,GetFinalPathNameByHandle已为Windows可以安装和读取的所有文件系统定义良好,无需额外的驱动程序或解决方法。但是,OpenFileByFileId仅为NTFS,ReFS和CsvFS定义。我不知道它是否为FAT或exFAT驱动器定义。但是,根据规范,它将不适用于网络共享驱动器(SMB)。

由于我遍历所有文件的方式,我可以选择只缓存文件名,但是缓存这些文件的内存效率极低,占用高达500MB的内存,而缓存不需要大约100MB的内存。是否有一个不同的API可以让我在给定file_id的情况下获取文件的名称?

0 个答案:

没有答案