win32 CreateFile2 api调用的目的是什么?

jco*_*der 7 winapi windows-8

他们在Windows 8中添加了一个新的API调用,CreateFile2 据我所知,它与现有CreateFile函数完全相同,只是它的参数打包方式有些不同.

已经添加了什么来实现这一点,因为我在文档中看不到任何内容.

Chu*_*urn 11

CreateFile实际上可以做的不仅仅是打开一个文件。CreateFile2创建的目的是为了将函数的“表面积”限制为 UWP 应用程序允许的功能,并且-因为 WACK 工具无法真正区分导入函数的“好”使用和“坏”使用,只是它正在被使用。

我在 C++ 库中使用的典型模式如下。我使用RAII 模式作为文件句柄以在使用 C++ 异常处理时支持(除了作为良好的现代 C++ 编码实践之外):

#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; }
Run Code Online (Sandbox Code Playgroud)

我的原因safe_handle是因为CreateFileCreateFile2被定义为返回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
Run Code Online (Sandbox Code Playgroud)

重要的是使用FILE_SHARE_READ而不是 0dwShareMode作为读取参数。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!
Run Code Online (Sandbox Code Playgroud)

对于写入,我请求DELETE权限,因为如果文件输出过程失败,我会使用SetFileInformationByHandlewithFILE_DISPOSITION_INFO进行清理。请参阅scoped.h

有关详细信息,请参阅游戏的双重用途编码技术


Bra*_* Ds 6

由于文件创建标志、文件属性标志和安全 QoS 标志复用到 CreateFile 的单个 DWORD (dwFlagsAndAttributes) 参数中,因此无法向 CreateFile 添加更多标志。创建操作的附加标志必须仅添加到 CreateFile2。例如 FILE_FLAG_OPEN_REQUIRING_OPLOCK 标志。该标志记录在FltCreateFile - 内核模式中