NTFS 目录上的 CreateFile 在 ReadFile 上失败
CreateFile on Directory in NTFS fails on ReadFile
据说可以实际打开和读取 NTFS 卷上的目录。但是,我尝试此操作的代码不起作用,所以我尝试了 google,它找到了我 this.
这里的关键观察结果似乎是您必须使用 FILE_FLAG_BACKUP_SEMANTICS。所以,把它剪下来,我基本上得到:
HANDLE hFile = CreateFile(L"C:\temp", GENERIC_READ, FILE_SHARE_READ,
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
DWORD dwFileSize = GetFileSize(hFile, 0);
char* buf = new char[dwFileSize];
DWORD dwBytesRead = 0;
BOOL b = ReadFile(hFile, buf, dwFileSize, &dwBytesRead, 0);
看起来很简单。不幸的是,它不起作用。
CreateFile
和 GetFileSize
都有效(句柄不是 INVALID_HANDLE_VALUE,非零且合理的文件大小),但 ReadFile
returns FALSE,dwBytesRead 为零,GetLastError returns 1 ("Incorrect function")。嗯
当我输入这个问题时,'Similar Questions' 提示显示 this. That business about using AdjustTokenPrivileges
made a lot of sense. However, it didn't help. Adding ReadFile (and using c:\temp) to that example gives the same behavior. A closer reading of the CreateFile docs 显示即使没有 SE_BACKUP_NAME 权限,由于管理员权限,我应该能够打开文件.
我尝试了多种排列方式:
- 指定目录名称的不同方式(
c:\temp
、c:\temp\
、\.\c:\temp
、\?\c:\temp\
等)。
- 不同目录
- 不同的驱动器
- 不同的分享选项(0,FILE_SHARE_READ,FILE_SHARE_READ | FILE_SHARE_WRITE)
- 不同的访问权限(
GENERIC_READ
、FILE_LIST_DIRECTORY
、FILE_LIST_DIRECTORY + FILE_READ_EA + FILE_READ_ATTRIBUTES
、FILE_LIST_DIRECTORY + FILE_READ_EA + FILE_READ_ATTRIBUTES + FILE_TRAVERSE
)
- 除了 FILE_FLAG_BACKUP_SEMANTICS(我认为是必需的)之外,我看不到任何可能适用的标志,但我尝试了 FILE_FLAG_NO_BUFFERING 和 4096 字节对齐的缓冲区。没有。
我(目前)正在尝试 152 个排列,并且 none 的 ReadFiles 正在工作。我错过了什么?
我原来的假设不正确吗?从目录中 'read' 真的不可能吗?还是我仍然缺少一些技巧?
我还应该提到什么?
- 我是 运行 管理员,可以在卷上执行 CreateFile。
- 我的程序是 64 位的,为 unicode 构建。
- Windows 7 x64
- NTFS 3.1 卷
- 外面多云(嘿,你永远不知道什么可能很重要...)
如果要打开流,则需要在路径中包含流名称 and/or 类型:
c:\foo:bar
A.K.A。 c:\foo:bar:$DATA
c:\foo::$INDEX_ALLOCATION
如果您不指定流,则使用默认的 $DATA 流。 $DATA 存储一个文件 "normal data".
如果你想要目录中的文件列表,那么你可以使用 GetFileInformationByHandleEx(FileIdBothDirectoryInfo)
(在旧系统上使用 NtQueryDirectoryFile
)。
看来乔纳森·波特给出了正确答案。尽管有提示,他还是选择不 post 他的评论作为答案。因此,我将根据他的回答创建一个以结束问题。
简而言之:"You can open a handle to a directory to do certain things, but calling ReadFile on it isn't one of them."
什么东西? These things。此列表包括:
- 备份读取
- 备份搜索
- 备份写入
- 通过句柄获取文件信息
- 获取文件大小
- 获取文件时间
- 获取文件类型
- ReadDirectoryChangesW
- 设置文件时间
总结:虽然您可以 "open" 目录和 "read" 关于它们的某些信息,但实际上您不能使用 ReadFile。如果您想阅读 DirName::$INDEX_ALLOCATION 信息,则必须使用不同的方法。
据说可以实际打开和读取 NTFS 卷上的目录。但是,我尝试此操作的代码不起作用,所以我尝试了 google,它找到了我 this.
这里的关键观察结果似乎是您必须使用 FILE_FLAG_BACKUP_SEMANTICS。所以,把它剪下来,我基本上得到:
HANDLE hFile = CreateFile(L"C:\temp", GENERIC_READ, FILE_SHARE_READ,
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
DWORD dwFileSize = GetFileSize(hFile, 0);
char* buf = new char[dwFileSize];
DWORD dwBytesRead = 0;
BOOL b = ReadFile(hFile, buf, dwFileSize, &dwBytesRead, 0);
看起来很简单。不幸的是,它不起作用。
CreateFile
和 GetFileSize
都有效(句柄不是 INVALID_HANDLE_VALUE,非零且合理的文件大小),但 ReadFile
returns FALSE,dwBytesRead 为零,GetLastError returns 1 ("Incorrect function")。嗯
当我输入这个问题时,'Similar Questions' 提示显示 this. That business about using AdjustTokenPrivileges
made a lot of sense. However, it didn't help. Adding ReadFile (and using c:\temp) to that example gives the same behavior. A closer reading of the CreateFile docs 显示即使没有 SE_BACKUP_NAME 权限,由于管理员权限,我应该能够打开文件.
我尝试了多种排列方式:
- 指定目录名称的不同方式(
c:\temp
、c:\temp\
、\.\c:\temp
、\?\c:\temp\
等)。 - 不同目录
- 不同的驱动器
- 不同的分享选项(0,FILE_SHARE_READ,FILE_SHARE_READ | FILE_SHARE_WRITE)
- 不同的访问权限(
GENERIC_READ
、FILE_LIST_DIRECTORY
、FILE_LIST_DIRECTORY + FILE_READ_EA + FILE_READ_ATTRIBUTES
、FILE_LIST_DIRECTORY + FILE_READ_EA + FILE_READ_ATTRIBUTES + FILE_TRAVERSE
) - 除了 FILE_FLAG_BACKUP_SEMANTICS(我认为是必需的)之外,我看不到任何可能适用的标志,但我尝试了 FILE_FLAG_NO_BUFFERING 和 4096 字节对齐的缓冲区。没有。
我(目前)正在尝试 152 个排列,并且 none 的 ReadFiles 正在工作。我错过了什么?
我原来的假设不正确吗?从目录中 'read' 真的不可能吗?还是我仍然缺少一些技巧?
我还应该提到什么?
- 我是 运行 管理员,可以在卷上执行 CreateFile。
- 我的程序是 64 位的,为 unicode 构建。
- Windows 7 x64
- NTFS 3.1 卷
- 外面多云(嘿,你永远不知道什么可能很重要...)
如果要打开流,则需要在路径中包含流名称 and/or 类型:
c:\foo:bar
A.K.A。c:\foo:bar:$DATA
c:\foo::$INDEX_ALLOCATION
如果您不指定流,则使用默认的 $DATA 流。 $DATA 存储一个文件 "normal data".
如果你想要目录中的文件列表,那么你可以使用 GetFileInformationByHandleEx(FileIdBothDirectoryInfo)
(在旧系统上使用 NtQueryDirectoryFile
)。
看来乔纳森·波特给出了正确答案。尽管有提示,他还是选择不 post 他的评论作为答案。因此,我将根据他的回答创建一个以结束问题。
简而言之:"You can open a handle to a directory to do certain things, but calling ReadFile on it isn't one of them."
什么东西? These things。此列表包括:
- 备份读取
- 备份搜索
- 备份写入
- 通过句柄获取文件信息
- 获取文件大小
- 获取文件时间
- 获取文件类型
- ReadDirectoryChangesW
- 设置文件时间
总结:虽然您可以 "open" 目录和 "read" 关于它们的某些信息,但实际上您不能使用 ReadFile。如果您想阅读 DirName::$INDEX_ALLOCATION 信息,则必须使用不同的方法。