【发布时间】:2019-05-09 09:41:22
【问题描述】:
短:
在我的 c++ 项目中,我需要读/写扩展文件属性。我使用备用数据流 (ADS) 来管理它。我的问题是,为了打开 ADS,我需要使用 CreateFile API。但这并不能满足我的需求。 NtCreateFile 将满足我的所有需求。 (或者NtSetEaFile 和NtQueryEaFile)但是NtCreateFile 不能直接从win32 控制台应用程序访问。
我知道我可以通过GetProcAdress 轻松使用此功能。但我想知道你们所有人的意见,如果我错过了什么?其他一些库已经在使用这种模式,例如 Chromium (https://github.com/chromium-googlesource-mirror/chromium/blob/1c1996b75d3611f56d14e2b30e7ae4eabc101486/src/sandbox/src/win_utils.cc function: ResolveNTFunctionPtr)
但我不确定,因为 c++ 项目不是一个爱好项目,我问自己是否危险。
我猜NtCreateFile 可能是最安全的方法,因为它有很好的文档记录并得到winternl.h 标头的支持。特别是因为这种方法自 Windows 2000 以来没有改变。但是 NtSetEaFile、NtQueryEaFile 完全符合我的需求。他们只记录了一半。存在 ZwSetEaFile 和 ZwQueryEaFile 的文档(自 Windows 2000 以来未更改)。
我想这样做的原因:
我想通过 ADS 从文件中写入和读取扩展属性。但是如果第一次写给定文件的扩展属性,我需要用OPEN_ALWAYS打开文件。如果文件不存在,它将创建一个新文件,即使我只访问不文件的内容流。为避免这种情况,我首先获取原始文件的句柄,并使用此句柄检查文件是否仍然存在。
但我不想写任何访问权限减少的文件,因为从我的角度来看,这是一个非常糟糕的模式。用户需要随时拥有对任何文件的完全访问权限。因此,我们打开所有带有标志FILE_SHARE_DELETE | 的句柄。 FILE_SHARE_READ | FILE_SHARE_WRITE。现在我参加了比赛。
auto hFile = CreateFileW(originalPath, …, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, …).
// this is the little race: if somebody at least rename originalPath the
// second CreateFileW call will cause the creation of a empty file with the
// path originalPath (the old path).
auto hADS = CreateFileW(originalPath + adsName, …, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_ALWAYS, …).
这是一个主要问题,尤其是因为在我们的测试中不时会发生这种情况。 NtCreateFile 将修复它,因为我可以在第一个 HANDLE 的帮助下创建第二个 HANDLE。因为没有种族。或者 NtSetEaFile 和 NtQueryEaFile 会有所帮助,因为我只需要一个 HANDLE。
问题是,应用程序不需要保存以备将来使用,因为无论如何 ADS 仅适用于 NTFS。谁知道NTFS什么时候会被交换。但我不想要一个片状的行为。我想相信这个方法。如果 API 将来会发生变化并且软件需要适应它,我很好。但我想确定的是,所有高于或等于 7 的 Windows 都可以处理它。有人分享一些经验吗?我很想听听他们的声音。
【问题讨论】:
-
但 NtCreateFile 不能从 win32 控制台应用程序直接访问这是不正确的。它的访问方式与
CreateFile相同。只需与 ntdll[p].lib 链接即可。控制台或非控制台不起任何作用。和 ADS != EA,你总是把它弄糊涂了。你想用EA我怎么理解 -
存在 ZwSetEaFile 和 ZwQueryEaFile 的文档 是的。在用户模式下 NtXxx == ZwXxx 两个名字都指向同一个函数
-
@RbMm 感谢您的遮阳篷。我对 ADS 和 EA 并不感到困惑。但是这两个概念都满足了我的需求。因为使用 ADS 我试图复制 EA 的行为。你确定链接到 ntdll[p].lib。我甚至可以使用该库访问 NtSetEaFile 吗?
-
我还没弄清楚如何链接到库。因为我认为 ntdll.dll 的概念是,它可以随着版本的不同而变化,包括 api。因此,我无法将静态链接到它。你知道一些示例项目吗?我找不到它们中的任何一个,这对我来说看起来很可靠。因此,如果我针对最新的 WDK 进行编译,则 lib 不仅仅包含对 dll 的地址的引用,那么我在另一边读到了什么?并且因为 WDK 保证可以与 WINdows 7-10 一起使用,所以我省了?
-
我无法将静态链接到它。 - 这是错误的。你可以链接它。绝对与您链接 kernel32.lib、user32.lib 等的方式相同。
标签: c++ winapi visual-c++ file-io