我创建了一个小框架,为多个文件系统/API(即 Win32、Posix、NFS)提供统一的 API。所说的 API 有点类似于 Posix——要访问一个文件,您需要“打开”它,为预期目的(r
或w
)rw
提供提示。类似的东西open_file("/abc/log.txt", access::rw)
。
由于 Win32 的“声明性”性质,在这个框架中支持 Win32 API 让我很头疼——您应该预先知道您计划在给定句柄上执行哪些操作并将相关的操作传递dwDesiredAccess
给相关(Nt)CreateFile()
调用。r/w/rw
不幸的是,除了通用提示之外,框架不知道客户端将执行什么操作(即更改所有者、写入属性等) 。而且我不愿意让 Win32 概念泄漏到我的框架中(即我不喜欢dwDesiredAccess
在我的open_file()
.
这是我尝试过的:
1. MAXIMUM_ALLOWED
想法:使用 MAXIMUM_ALLOWED 打开相关句柄——我将尽我所能,如果缺少某些权利,相关操作(例如set_mime()
)将简单地以access denied
.
问题:
- 它不适用于只读文件或卷(
(Nt)CreateFile()
失败access denied
) - MSDN警告说,如果 FAT 卷上正在进行碎片整理 - 尝试以这种方式打开目录将失败
MAXIMUM_ALLOWED
一般来说,由于某种原因似乎不赞成使用
2. 必要时重新打开对象
想法:代表所有需要额外访问权限的操作(例如requires r/w/rw
)重新打开具有所需访问权限的对象。GENERIC_READ
GENERIC_WRITE
delete()
DELETE
问题:
- 重新打开对象并不便宜
- 通过第二个对象所做的更改可以被静默覆盖,例如:
set_mtime()
重新打开文件FILE_WRITE_ATTRIBUTES|SYNCHRONIZE
- 调用
NtSetInformationFile(... FileBasicInformation)
更新元数据并关闭句柄 - 后来原始句柄被关闭,它会导致数据刷新并静默覆盖
ModifiedTime
先前设置的set_mtime()
3.复制句柄而不是重新打开对象
想法:与上一节相同,但不是重新打开对象——复制原始句柄(要求新的访问权限):
HANDLE h;
HANDLE hp = GetCurrentProcess();
CHECK_WIN32( DuplicateHandle(hp, hFile, hp, &h, FILE_WRITE_ATTRIBUTES|SYNCHRONIZE, FALSE, 0) );
问题:
- 每次我需要执行(非普通读/写)操作时复制(和关闭)文件句柄似乎过多且有些昂贵
DuplicateHandle()
文档警告(未提供任何详细信息)要求额外访问可能会失败。它在我检查过的所有用例中都运行良好(通常要求在打开的句柄上使用DELETE
/之类的东西),但显然 Win32 API 不提供任何保证:-/FILE_WRITE_ATTRIBUTES
GENERIC_READ
...否则方法似乎有效。
底线:
我正在寻找解决MAXIMUM_ALLOWED
问题的方法。(或者对替代方法的建议,也许?)