When a new Windows version comes out, I’m always curious about the new Windows API (Win32) functions that are added to the release.
With Windows 8, things get a little more complicated, as there are desktop apps and there are metro apps. Now, for every Windows API function the documentation states whether this API is valid for desktop apps only or for desktop apps and metro apps.
One classic function is CreateFile. This is one of the oldest functions – exists since the very first Windows NT version. In Windows 8, it’s marked for desktop apps only. This may be understandable, as the Windows Runtime has other ways to use files, such as the StorageFile class. However, Windows 8 has a new function called CreateFile2. This one, in contrast to CreateFile, can be used in desktop and metro apps. Here’s its prototype:
Here’s the prototype of CreateFile:
The first four arguments of CreateFile2 exist in both CreateFile and CreateFile2. The new extended parameters structure of CreateFile2 simply packages the “missing” arguments into an single optional structure:
This structure actually adds nothing to what CreateFile can specify. The dwFlagsAndAttributes of CreateFile is logically split to three groups of flags represented by dwFileAttributes, dwFileFlags and dwSecurityQosFlags in this structure for CreateFile2. Although the split is a good thing, it doesn’t explain why CreateFile is forbidden in metro style apps. Furthermore, the documentation for CreateFile2 states that in metro apps this function can only open files and directories (and not things like pipes, mailslots, consoles, etc.).
So why is CreateFile forbidden in metro apps? Perhaps it does allow opening something that CreateFile2 forbids?
I decided to try calling it from a metro app. Trying to just use CreateFile would not compile, as a set of #ifdef/#endif is placed inside the Windows headers to prevent compiling a forbidden API. This, however, can be circumvented easily. We can just create the correct prototype manually:
This is just the CreateFile declaration from the docs wrapped in an extern “C” declaration; this is important, otherwise the liker would complain of an unresolved external (trying to look for C++ linkage). Also, note the function is declared as CreateFileW (the Unicode version) and not simply CreateFile, as CreateFile is actually a macro, and would not have been found by the linker.
Let’s add a simple call to this CreateFileW in a blank C++ metro style application in the BlankWindow constructor:
This code tries to open a text file. This fails with error code 5 (access denied), as does CreateFile2. Although I set up the manifest with access to the documents library and set up a TXT file association, it refuses to work.
There doesn’t seem to be a noticeable difference between CreateFile and CreateFile2. I don’t understand at this time why CreateFile2 exists, apart from the convenience of that extra optional structure. There’s a room for further investigation, perhaps looking at NtDll.dll to see if these call different system services (unlikely, but worth a check).