CreateFile 实际上可以做的不仅仅是打开一个文件。 CreateFile2 的创建是为了将函数的“表面积”限制为仅允许 UWP 应用程序使用的功能,并且因为 WACK 工具无法真正区分导入的“好”使用和“坏”使用功能,只是它正在被使用。
我在 C++ 库中使用的典型模式如下。我使用RAII pattern 作为文件句柄以支持在使用 C++ 异常处理时(除了很好的modern C++ coding practice):
#include <assert.h>
#include <memory>
struct handle_closer
{ void operator()(HANDLE h) noexcept { assert(h != INVALID_HANDLE_VALUE); if (h) CloseHandle(h); } };
using ScopedHandle = std::unique_ptr<void, handle_closer>;
inline HANDLE safe_handle(HANDLE h) noexcept { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; }
我有safe_handle 的原因是因为CreateFile 和CreateFile2 被定义为返回INVALID_HANDLE_VALUE (-1) 而不是返回0 失败。大多数其他返回句柄的 Win32 函数在失败时返回 0,我已经确认没有任何情况下“0”是有效的 Win32 句柄。
为了阅读我使用:
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile(safe_handle(
CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr)));
#else
ScopedHandle hFile(safe_handle(
CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, nullptr)));
#endif
if (!hFile)
// Error
使用FILE_SHARE_READ 代替0 来读取dwShareMode 参数很重要。 UWP 应用对现有文件没有独占读取权限,因此如果您使用“独占”共享模式(即 0),调用将失败。
对于写入文件:
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile(safe_handle(
CreateFile2(szFile, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, nullptr)));
#else
ScopedHandle hFile(safe_handle(
CreateFileW(szFile, GENERIC_WRITE | DELETE, 0, nullptr, CREATE_ALWAYS, 0, nullptr)));
#endif
if (!hFile)
// Error!
对于写作,我请求DELETE 权限,因为如果文件输出过程失败,我使用SetFileInformationByHandle 和FILE_DISPOSITION_INFO 进行清理。见scoped.h。
请参阅Dual-use Coding Techniques for Games 了解更多信息。