Specifying correct device type with CTL_CODE for control devices

I am using a control device allocated via WdfControlDeviceInitAllocate. I want to make sure I am defining I/O control codes correctly via the CTL_CODE macro. The DeviceType parameter of the macro is what I'm having trouble with.

Documentation says that I cannot use the WdfDeviceInitSetDeviceType function with control device initialization structures. So I don't know the device type to set for the control code. I looked at the NONPNP sample and I see that they use a custom device type, but that is only used in the CTL_CODE macro and not actually used anywhere in the driver code. Is there something else I need to do?

TLDR: don't worry about the device type. it is a DOS app compat thing

The only bits of an ioctl code that have any inherent meaning are bits 15:14 (access) and 1:0 (buffer type). Everything else is just private communication between your driver and your apps. You can use whatever numbers you want.

Interesting, I wonder where the < 0x8000 Microsoft reserved values come from. Maybe the DOS compatibility that was mentioned?

No, DOS didn't use 32-bit ioctl codes. Think about it this way. How could it ever be an issue? Who is going to be sending you ioctls?

Now, if you are working in a HID driver or a streaming driver, where there is already a set of ioctl codes, then you want to follow the rules more closely, so that there is not a chance for a future conflict. But in a control device, you're never going to see ioctls from anyone else, and no other driver is going to see the ioctls you send. You can use whatever numbers you want (except for those 4 bits).

Bit 13, the "Custom" bit should also be respected... though it has never mattered to the best of my knowledge. It's still part of the spec, and we teach people to set it correctly:

Values of less than 0x800 are reserved for Microsoft. Values of 0x800 and higher can be used by vendors. Note that the vendor-assigned values set the Custom bit.

(As an aside: I remember "back in the day"... the guy who owned the I/O Manager was surprised when I told him there was a "custom" bit in the IOCTL control code. "I never knew that," he said. IIRC, he was the one who took over the I/O Manager from Darrel Havens).