Hi all. I'm now getting much more detail about the various devices installed in the system. However my enumerator has (I think) got a problem with distinguishing between KSCATEGORY_RENDER and KSCATEGORY_CAPTURE categories. It would appear to be getting _all_ entries for the KSCATEGORY_AUDIO hive. It is worth noting I have also tried querying the registry using this: SetupDiGetDeviceRegistryProperty(hDevInfo,&DevInfoData,SPDRP_DEVTYPE,NULL,(P BYTE)&dw,sizeof(dw),&reqSize); The theory here being that the enumerations indicate unambiguously what type of device we have. The MSDN link is http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/k march/devobjts_5hnr.asp Howver this fails with GetLastError() returning an 'invalid data' message. I have taken the liberty of attaching the relevant C++ class which is reasonably well commented. If anyone would care to comment on why the enumeration returns both Capture AND Render devices I would be delighted. It should only require a #include to an existing project with a call as shown in the header comments. TVMIA Jerry -- Attached file included as plaintext by Ecartis -- -- File: DEVENUM2.H /* KS device enumerator Sample usage: Chordia::CDeviceEnumerator enumerator; std::vector<Chordia::CDeviceDescriptor> ipnames; std::vector<Chordia::CDeviceDescriptor> opnames; // do the enumeration for AUDIO + CAPTURE devices only if (enumerator.enumerate(KSCATEGORY_AUDIO,KSCATEGORY_CAPTURE,ipnames) > 0) { for (std::vector<Chordia::CDeviceDescriptor>::iterator it = ipnames.begin(); it != ipnames.end(); ++it) { // stuff .... } } STATIC_KSCATEGORY_AUDIO STATIC_KSCATEGORY_RENDER STATIC_KSCATEGORY_CAPTURE (C) Jerry Evans 2003 jerry_ks@xxxxxxxxxxxxx Permisssion to redistribute granted for source and binary formats. Please do not modify any of this comment block */ //----------------------------------------------------------------------------- // auto-include relevant libraries //----------------------------------------------------------------------------- #include <Setupapi.h> #pragma comment( lib, "setupapi.lib") //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- namespace Chordia { class CDeviceDescriptor { public: std::string m_handle; std::string m_description; std::string m_name; std::string m_manufacturer; UINT m_id; CDeviceDescriptor() { m_id = 0;} CDeviceDescriptor(const CDeviceDescriptor& arg) { m_id = arg.m_id; m_handle = arg.m_handle; m_description = arg.m_description; m_name = arg.m_name; m_manufacturer = arg.m_manufacturer; } CDeviceDescriptor& operator=(const CDeviceDescriptor& arg) { m_id = arg.m_id; m_handle = arg.m_handle; m_description = arg.m_description; m_name = arg.m_name; m_manufacturer = arg.m_manufacturer; return (*this); } }; //----------------------------------------------------------------------------- // Enumerate kernel devices and return internal handle name and descriptions //----------------------------------------------------------------------------- class CDeviceEnumerator { public: CDeviceEnumerator() {} // enumerate names of devices matching GUIDS // size_t enumerate(IN const GUID category, IN const std::vector<GUID>& guids, OUT std::vector<CDeviceDescriptor>& descs) // size_t enumerate(IN const GUID category, IN const GUID& mode, OUT std::vector<CDeviceDescriptor>& descs) { std::map<std::string,UINT> id_map; // Get a handle to the device set specified by the guid HDEVINFO hDevInfo = SetupDiGetClassDevs(&category, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); // failure ? if (hDevInfo == INVALID_HANDLE_VALUE) { return 0; } // DWORD index = 0; // Loop through members of the set and get details for each while (true) { SP_DEVICE_INTERFACE_DATA DID; SP_DEVICE_INTERFACE_DATA DIDAlias; SP_DEVINFO_DATA DevInfoData; DID.cbSize = sizeof(DID); DID.Reserved = 0; DIDAlias.cbSize = sizeof(DIDAlias); DIDAlias.Reserved = 0; ZeroMemory(&DevInfoData,sizeof(DevInfoData)); DevInfoData.cbSize = sizeof(DevInfoData); DevInfoData.Reserved = 0; // enumerate all KS_CATEGORY_AUDIO ? if (SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &category, index++, &DID) == FALSE) { // This just means that we've enumerate all the devices - it's not a real error break; } // new scope so buffer will come & go { // Get details for the device registered in this class DWORD size = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR); // use vector so it will clean up afterwards std::vector<BYTE> buffer(size,0); // SP_DEVICE_INTERFACE_DETAIL_DATA* pDevInterfaceDetails = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(&buffer[0]); // pDevInterfaceDetails->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &DID, pDevInterfaceDetails, size, NULL, &DevInfoData)) { continue; } // check additional category guids which may (or may not) have been supplied if (!SetupDiGetDeviceInterfaceAlias(hDevInfo, &DID, &mode, &DIDAlias)) { continue; } // Check if the this interface alias is enabled. if (!DIDAlias.Flags || (DIDAlias.Flags & SPINT_REMOVED)) { continue; } // CDeviceDescriptor desc; desc.m_handle = pDevInterfaceDetails->DevicePath; // this is how I test device 'type' at the moment !!!! /* CKsAudFilter filter; if (filter.Instantiate(pDevInterfaceDetails->DevicePath) == S_OK) { if (mode == KSCATEGORY_RENDER) { if (filter.CountRenderPins() == 0) { continue; } } if (mode == KSCATEGORY_CAPTURE) { if (filter.CountCapturePins() == 0) { continue; } } } */ // DWORD reqSize = 0; BYTE name[64]; DWORD dw = 0; BOOL b = SetupDiGetDeviceRegistryProperty(hDevInfo, &DevInfoData, SPDRP_DEVTYPE, NULL, (PBYTE)&dw, sizeof(dw), &reqSize); // get friendly name if (SetupDiGetDeviceRegistryProperty(hDevInfo, &DevInfoData, SPDRP_LOCATION_INFORMATION, NULL, // don't need the reg type &name[0], sizeof(name), &reqSize) == TRUE) { desc.m_name = reinterpret_cast<TCHAR*>(name); name[reqSize] = '\0'; } // get device description if (SetupDiGetDeviceRegistryProperty(hDevInfo, &DevInfoData, SPDRP_DEVICEDESC, NULL, // don't need the reg type &name[0], sizeof(name), &reqSize) == TRUE) { desc.m_description = reinterpret_cast<TCHAR*>(name); name[reqSize] = '\0'; } // get the manufacturers name if (SetupDiGetDeviceRegistryProperty(hDevInfo, &DevInfoData, SPDRP_MFG, NULL, // don't need the reg type &name[0], sizeof(name), &reqSize) == TRUE) { desc.m_manufacturer = reinterpret_cast<TCHAR*>(name); name[reqSize] = '\0'; } // this gives us device numbering if we have multiple (say) USB devices std::string strDesc = desc.m_description; UINT id = 1; // find the name std::map<std::string,UINT>::iterator imi = id_map.find(strDesc); if (imi != id_map.end()) { // increment the count id = ++imi->second; } else { // insert as <Name> <1> id_map.insert(std::make_pair(strDesc,1)); } // desc.m_id = id; descs.push_back(desc); } } // clean up and go home SetupDiDestroyDeviceInfoList(hDevInfo); // return descs.size(); } }; //----------------------------------------------------------------------------- // end namespace //----------------------------------------------------------------------------- }; //----------------------------------------------------------------------------- // end file //----------------------------------------------------------------------------- ****************** WDMAUDIODEV addresses: Post message: mailto:wdmaudiodev@xxxxxxxxxxxxx Subscribe: mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=subscribe Unsubscribe: mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=unsubscribe Moderator: mailto:wdmaudiodev-moderators@xxxxxxxxxxxxx URL to WDMAUDIODEV page: http://www.wdmaudiodev.de/