They have added a new API call in windows 8 called CreateFile2
which as far as I can tell does exactly the same as the existing CreateFile
function only it packages up its parameters somewhat differently.
What has been added to make this necessary, as I can't see anything in the documentation.
CreateFile provides for creating a file or device handle that is either synchronous or asynchronous.
An application can retrieve the file attributes by using the GetFileAttributes or GetFileAttributesEx function. The CreateFile and SetFileAttributes functions can set many of the attributes.
CreateFile
actually can do a lot more than just open a file. CreateFile2
was created to both restrict the 'surface area' of the function to just the functionality allowed for UWP apps, -and- because the WACK tool can't really distinguish between 'good' use and 'bad' use of an import function, just that it is being used at all.
The typical pattern I use in my C++ libraries is as follows. I use an RAII pattern for the file handle to support when C++ Exception Handling is used (in addition to just being good 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; }
The reason I have
safe_handle
is becauseCreateFile
andCreateFile2
are defined to returnINVALID_HANDLE_VALUE
(-1) instead of returning 0 for a failure. Most other Win32 functions that return handles return 0 for a failure, and I've confirmed that there's no case where a '0' is a valid Win32 handle.
For reading I use:
#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
It is important to use
FILE_SHARE_READ
instead of 0 for thedwShareMode
parameter for reading. UWP apps don't have exclusive read access to existing files, so calls would fail if you used 'exclusive' share mode (i.e. 0).
And for writing a file:
#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!
For writing I request the
DELETE
permission because I useSetFileInformationByHandle
withFILE_DISPOSITION_INFO
to clean up if the file output process fails. See scoped.h.
See Dual-use Coding Techniques for Games for more information.
Due to the multiplexing of file creation flags, file attribute flags and security QoS flags into a single DWORD (dwFlagsAndAttributes) parameter for CreateFile, there is no way to add any more flags to CreateFile. Additional flags for the create operation must be added to CreateFile2 only. For example FILE_FLAG_OPEN_REQUIRING_OPLOCK flag. This flag is documented FltCreateFile - kernel mode
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With