Maybe your user mode Plug’n’Play implementation?
I did factor Microsoft’s everything-in-a-single-source-file sample code into separate files/classes. It’s possible that I introduced some subtle change in the order of initialization steps. I’m going to compare mine against the sample (call-by-call) to see whether they’re different.
Maybe DIGCF_PRESENT flag forgotten when building the set of device interfaces?
I’m actually using CfgMgr32 APIs in my console test program, and I am specifying CM_GET_DEVICE_INTERFACE_LIST_PRESENT
:
_Check_return_ //
static std::wstring GetDevicePath(REFGUID interfaceClassGuid)
{
std::wstring result;
// Request the minimum buffer size to contain the (NUL-delimited) list of devices that support the specified interface
ULONG listSizeInWords = 0;
auto cr = ::CM_Get_Device_Interface_List_SizeW(
&listSizeInWords, // Pointer to a location that receives the required length, in characters
const_cast<LPGUID>(&interfaceClassGuid), // GUID that identifies a device interface class
nullptr, // Device instance ID
CM_GET_DEVICE_INTERFACE_LIST_PRESENT); // Flags
if (cr != CR_SUCCESS)
{
std::wcerr << L"\tERROR: Unable to retrieve device interface list size; CONFIGRET: " << Text::CrToString(cr).c_str();
}
else if (listSizeInWords <= 1)
{
std::wcerr << L"\tWARNING: No active device interfaces found. Is the immersed-display-driver loaded?" << std::endl;
}
else
{
// Use 'fill' ctor to preallocate (and initialize with NULs) the minimum required buffer to contain the list
std::wstring deviceItfList(listSizeInWords, L'\0');
// Query the (NUL-delimited, double-NUL-terminated) list of device paths
cr = ::CM_Get_Device_Interface_ListW(
const_cast<LPGUID>(&interfaceClassGuid), // GUID that identifies the device interface class
nullptr, // Device instance ID
&deviceItfList[0], // Buffer to receive list
listSizeInWords, // Length (in wchar_t), of the provided buffer
CM_GET_DEVICE_INTERFACE_LIST_PRESENT); // Flags
if (cr != CR_SUCCESS)
{
std::wcerr << L"\tERROR: Unable to retrieve device interface list; CONFIGRET: " << Text::CrToString(cr).c_str();
}
else
{
// Convert the NUL-delimited list to a vector<wstring>
auto deviceInterfaces = Text::Split(deviceItfList.c_str());
ASSERT(!deviceInterfaces.empty()); // We checked listSizeInWords above, so this shouldn't be empty
// We're looking for our custom driver interface, so there should only be ONE device in the list
if (1 < deviceInterfaces.size())
{
std::wcerr << L"\tWARNING: More than one device interface instance found. Selecting FIRST matching device."
<< std::endl;
}
result = deviceInterfaces[0];
}
}
return result;
}
Also, I’m getting the same Device Path string both before and after the disable-enable:
c:\display-driver-v3\Windows\bin\Debug>display-driver-ioctl-tester.exe
INFO: Got device path: "\\?\ROOT#DISPLAY#0000#{580fe7df-137a-45f1-9998-7b1f006cdc43}"
ERROR: Failed to open the device "\\?\ROOT#DISPLAY#0000#{580fe7df-137a-45f1-9998-7b1f006cdc43}"; Access is denied.
(here I manually disable and re-enable the driver)
c:\display-driver-v3\Windows\bin\Debug>display-driver-ioctl-tester.exe
INFO: Got device path: "\\?\ROOT#DISPLAY#0000#{580fe7df-137a-45f1-9998-7b1f006cdc43}"
(...successful output follows...)
Too extensive use of old (but not obsolete) kernel mode debugging techniques might not be conclusive here.
I was hoping that if I traced the CreateFile
API to the point of failure (down in the kernel), I’d have an ‘Ah Hah!’ moment. Unfortunately, I didn’t know how to interpret the results. It was an interesting exercise, though. I ordered Windows Internals 1 & 2, edition 7 yesterday (along with some driver development books) so I can learn more about this.
This is a User Mode Driver. WDK docs explain various UMDF debugging techniques which might be worth a closer look…
I’m setting that up again so I can record the actual flow through the driver. Once I had the driver working, I’d switched back to the Visual Studio debugger for the IOCTL stuff, because it’s so much more familiar.
But now I need to break on driver load and view trace output. I will have a look at the UMDF debugging techniques in the WDK docs again to see if I missed anything, but IIRC, I need to go back to WinDbg…, WdfVerifier, TraceView, etc. for that.
Cheers.