Ch11.15: NT File APIs

Overview

Modern Windows (NT, 2000, XP, 7, 10, 11) is built on the NT kernel. The lowest-level user-mode entry points for file I/O are the native system calls:

These live in ntdll.dll and are the same functions the Win32 subsystem itself calls. A parallel set of entry points with the Zw prefix (ZwCreateFile, …) exist as well; they differ only in whether the previous-mode parameter is set to KernelMode or UserMode. For user-mode code they behave identically.

fast_io exposes the NT layer through:

The programming model is exactly the same pattern as posix_file and win32_file.

Opening a File with nt_file


#include <fast_io.h>
#include <fast_io_device.h>

int main()
{
    using namespace ::fast_io::iomnp;

    // The constructor translates open_mode into the corresponding
    // NtCreateFile parameters (DesiredAccess, CreateDisposition, ...).
    ::fast_io::nt_file nf(u8"hello_nt.txt", ::fast_io::open_mode::out);

    println(nf, u8"Hello from nt_file!");

    ::std::size_t const n{42zu};
    println(nf, u8"The answer is: ", n);
    // NtClose is invoked automatically when `nf` goes out of scope.
}
      

Wrapping an Existing HANDLE


#include <fast_io.h>
#include <fast_io_device.h>

void inspect(void* nt_handle)
{
    using namespace ::fast_io::iomnp;

    // Non-owning view. No NtClose on destruction.
    ::fast_io::nt_io_observer observer{
        static_cast<::fast_io::nt_io_observer::native_handle_type>(nt_handle)};

    println(observer, u8"Written through an nt_io_observer\n");
    println(::fast_io::mnp::handlevw(observer.native_handle()));
}

int main()
{
    ::fast_io::nt_file nf(u8"inspect.txt", ::fast_io::open_mode::out);
    inspect(nf.native_handle());
}
      

Relative Opens

Because NtCreateFile natively accepts a RootDirectory handle and a relative ObjectName, the NT layer is the most natural home for at(dir) on Windows:


#include <fast_io.h>
#include <fast_io_device.h>

int main(int argc, char** argv)
{
    using namespace ::fast_io::iomnp;

    ::fast_io::nt_file dir{::fast_io::mnp::os_c_str(argv[1]),
                           ::fast_io::open_mode::directory};
    ::fast_io::nt_file nf(at(dir), u8"relative.txt",
                          ::fast_io::open_mode::out);
    println(nf, u8"Opened through NtCreateFile with a root directory\n");
}
      

Why Use nt_file Directly?

Most programs should just use ::fast_io::native_file (which aliases to nt_file on NT) or ::fast_io::iobuf_file. You reach for nt_file directly when you need:

Summary