“I would write a driver that creates a WDF device object. I would then open this device from user-mode and send custom IO control requests” – A typical user-kernel communication scenario.
Today, when I was doing this, I hit an issue opening the device in user-mode. I received ERROR_ACCESS_DENIED. User mode application is running with admin credentials, then what went wrong?
I used WinObj to confirm that my DosDevice and Device are set correctly. I also confirmed that in user-mode, I am using path as “\.MyDevice” (L”.MyDevice”).
If you have not used WinObj, it is a great tool from Microsoft to explore Windows Object Manager Namespace and Security ACLs of these objects.
I tried all access modes – GENERIC_READ, GENERIC_WRITE, BOTH (GENERIC_READ | GENERIC_WRITE) and NONE (0). I also tried different share modes – FILE_SHARE_[READ | WRITE], NONE (0).
I should admit, that was more of hit-try from frustration. And that does not help 🙂
Then, I looked at the way I created my device.
WdfDeviceInitSetCharacteristics(pWDFDeviceInit, FILE_DEVICE_SECURE_OPEN, FALSE);
This is also fine. Device characteristics was to Secure Open and since this was the only characteristic I was setting, the third argument was False.
So, I went another step back…
pWDFDeviceInit = WdfControlDeviceInitAllocate(*pDriver, &SDDL_DEVOBJ_KERNEL_ONLY);
With SDDL_DEVOBJ_KERNEL_ONLY, I am setting the device to be only accessible from Kernel. I need to set it to SDDL_DEVOBJ_SYS_ALL to allow Kernel and user mode code running as System! Problem found and fixed!
Reference SDDL for Device Objects on MSDN.
Since there was a lot of discussion around this on various forums and none pointed me to this direction, I though it be a good idea to document my fix as well. Hope this helps!