Can someone please explain to me in simple English how Windows handles device interface GUIDs? When I look through the WDK header files, I see lots of stuff about DEVINTERFACE_DISK, but nothing at all about DEVINTERFACE_SOUND (or Audio, or Media, or…). Hm… the list in guiddef.h seems to be incomplete! Hm…
Here’s what I’m trying to do: I wrote an WaveCyclic miniport driver, it works fine, and it creates an unnamed device that successfully shows up in the Device Manager and in the Windows Media Player list of streamable devices. It even streams audio. Hooray.
But now, I want to send an IOCTL into it. I need to command it to do something specific that isn’t an ordinary audio function. It’s a “device specific control”, so to speak.
I started from the MSVAD sample in the WDK, and used the .inf file that came with that example. I have this audio device (call it “msvad”, but it’s actually unnamed), and it shows up in all the right places, and it actually streams audio. When I look in the registry I see that it has an interface, and it’s the right one that I specified in the .inf file.
HOWEVER… the SetupDiGetClassDevs() function only works with the class GUID, not the interface GUID. When I enumerate the members of the device class I get the correct list, but when I set the DIGCF_DEVICEINTERFACE and pass in the device interface GUID, it returns an empty information set.
When I then use DIGCF_ALLCLASSES I get the expected big huge list of everything on the system, but if I attempt to restrict that list with a DEVINFO_DATA structure I got from SetupDiEnumDeviceInfo, it doesn’t work (error 259, end of list).
So, you’re probably thinking there’s something wrong with my device interface GUID, right?
Nope… in fact, if I use one of the canned device interface classes GUID_DEVINTERFACE_DISK, I get an empty information set too.
Can someone tell me what might be going on here? My code is about as vanilla as it gets, here’s an example:
HDEVINFO deviceInfoSet;
int memberIndex = 0;
SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData;
SP_DEVINFO_DATA MyDeviceInfo;
//
// look for all audio devices that are actually present on the system
// (search by device class, not interface class)
//
deviceInfoSet = SetupDiGetClassDevs(pGuid, NULL, NULL, DIGCF_PRESENT);
if(deviceInfoSet == INVALID_HANDLE_VALUE)
{
printf(“invalid handle\n”);
return -1;
}
do
{
MyDeviceInterfaceData.cbSize = sizeof(MyDeviceInterfaceData);
success = SetupDiEnumDeviceInterfaces
(deviceInfoSet,
NULL /* &MyDeviceInfo */,
&requestedInterfaceGuid,
memberIndex,
&MyDeviceInterfaceData);
// Find out if interface data was retrieved.
if (!success)
{
// FAILS HERE - Windows says there are no devices
// exporting my interface, even though they’re
// actually present on the system
lastError = GetLastError();
// …
return -2;
}
else
{
// A device is present.
success = SetupDiGetDeviceInterfaceDetail
(deviceInfoSet,
&MyDeviceInterfaceData,
NULL,
0,
&bufferSize,
NULL);
if (!success)
{
lastError = GetLastError();
// …
return -3;
}
// Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
detailDataBuffer = (SP_DEVICE_INTERFACE_DATA *) GlobalAlloc(GPTR, bufferSize);
// Store cbSize in the first 4 bytes of the array
detailDataBuffer->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
// Call SetupDiGetDeviceInterfaceDetail again.
// This time, pass a pointer to DetailDataBuffer
// and the returned required buffer size.
success = SetupDiGetDeviceInterfaceDetail
(deviceInfoSet,
&MyDeviceInterfaceData,
detailDataBuffer,
bufferSize,
(DWORD *) &bufferSize,
NULL);
if (!success)
{
lastError = GetLastError();
// …
return -4;
}
// Skip over cbsize (4 bytes) to get the address of the devicePathName.
pDevicePathName = ((char *) detailDataBuffer) + 4; // sizeof(long) on XP
// Get the String containing the devicePathName
printf(“found: device path name = %s\n”, pDevicePathName);
// Free the memory allocated previously by AllocHGlobal.
GlobalFree(detailDataBuffer);
deviceFound = 1;
break;
}
memberIndex = memberIndex + 1;
}
while (!(lastDevice));
SetupDiDestroyDeviceInfoList(deviceInfoSet);