背景:我知道在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的情况下获取文件的名称?