Using CreateFileW to get a handle to a display adapter device for DeviceIoControl

I’m a bit confused about the meaning of CreateFileW and its arguments in the context of a display adapter device. Here’s what I’m currently using:

// Open the virtual display device
hDevice = ::CreateFileW(
    devicePath.c_str(),                 // Name of the device to be opened
    GENERIC_WRITE | GENERIC_READ,       // Requested access to the device
    FILE_SHARE_READ | FILE_SHARE_WRITE, // Requested sharing mode of the device
    nullptr,                            // Default security attributes
    OPEN_EXISTING,                      // Disposition
    0,                                  // Device attributes and flags
    nullptr);                           // No template file to copy file attributes from
  • Since I’m talking to an existing adapter, I guess I would have expected to call OpenFile – not sure what’s being ‘created’ here.

  • If my process exits without calling CloseHandle on the returned handle, is this cleaned up like a file handle would be?

  • Requested access – since I’m just making DeviceIoControl calls with the returned handle, can I just pass zero here?

  • Requested sharing mode – If RequestedAccess param is zero, does this matter?

not sure what’s being ‘created’ here
A new kernel object is created, and it maps to existing “thing” (device or disk file).
OpenFile is old deprecated name from windows 3.x times.

Requested access – since I’m just making DeviceIoControl calls with the returned handle, can I just pass zero here?
Just try it :wink: Access rights are set up when CreateFile is called. They can be changed later, but why not to specify it upfront if you know what you need ?
DeviceIoControl does not change access rights.

–pa

If my process exits without calling CloseHandle on the returned handle, is this cleaned up like a file handle would be?

It IS a file handle. No more, no less. The same semantics apply.

1 Like

Requested access – since I’m just making DeviceIoControl calls with the returned handle, can I just pass zero here?

Your ioctl code indicates whether it needs FILE_READ_ACCESS or FILE_WRITE_ACCESS. You need to have the corresponding permission in your CreateFile call.

Requested sharing mode – If RequestedAccess param is zero, does this matter?

Exactly like a file. If you specify 0, then no one else can open the handle for read or write.

1 Like

Just try it :wink: Access rights are set up when CreateFile is called.
They can be changed later, but why not to specify it upfront if you know what you need?
DeviceIoControl does not change access rights.

I guess what I’m trying to understand is whether access rights (read/write/execute) have anything to do with IOCTL. I’m not really sure what ‘reading’ or ‘writing’ would mean in the context of a display adapter (streaming/capturing video?), never mind ‘execute’.

All of the examples of this that I can find are for devices where the meaning of reading/writing is fairly obvious (e.g. disk drive), so they always request read and/or write access. I only need to make DeviceIoControl calls, so I’m wondering if I should just request Access Rights of 0 (no read, write or execute access)?

I assume that the same is true for Sharing Mode – it doesn’t affect DeviceIoControl, so I can just pass 0 (no shared read, write or delete) into CreateFileW, and since I didn’t request any access rights either, the OS or some other process won’t be prevented from accessing the adapter…?

Just try it

Problem is that I’m getting AccessDenied back from CreateFileW, and I’ve tried various combinations of these parameters without success. When dealing with files, I can reason about which flags make sense, but I’m not clean on how this applies to a display adapter.

I suspect the AccessDenied error status is unrelated to these, but diagnosing/debugging is much simpler if I have reason to believe I’m passing reasonable values to CreateFileW.

Your ioctl code indicates whether it needs FILE_READ_ACCESS or FILE_WRITE_ACCESS.
You need to have the corresponding permission in your CreateFile call.

Ah! I hadn’t made that connection. I’m using only my own custom IOCTL codes, e.g.:

constexpr ULONG IOCTL_CONNECT_DISPLAY = CTL_CODE(FILE_DEVICE_VIDEO, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS);

…and none of them are stateful.

Exactly like a file. If you specify 0, then no one else can open the handle for read or write.

Sure, but if I open the handle with FILE_ANY_ACCESS (0), then there would be no need to specify any sharing modes, correct?

I just want to make sure that I won’t interfere with (or block) the OS, or anything else that might access the display adapter.

EDIT: Hmmm, maybe I’ve got that backwards. Maybe I need to specify share read, write and delete in order to ensure that I’m not interfering with any other processes, regardless of whether or not I’m using those access rights…

OK, this seemed to work, and it’s consistent with at least one code sample I’ve looked at:

        // Open the virtual display device
        hDevice = ::CreateFileW(
            devicePath.c_str(),                 // Name of the device to be opened
            0,                                  // No access to the device
            FILE_SHARE_READ | FILE_SHARE_WRITE, // Requested sharing mode of the device
            nullptr,                            // No security attribute struct (e.g. default)
            OPEN_EXISTING,                      // No special create flags
            0,                                  // No device attributes
            nullptr);                           // No template file to copy file attributes from

https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-generic_mapping

for all kinds of objects, the generic rights are mapped to specific ones. this can get very complicated