/*++ Copyright (c) 1997 Microsoft Corporation Module Name: infoset.h Abstract: Handles setup API device infosets Author: Vlad Sadovsky (vlads) 10-Jan-1999 Environment: User Mode - Win32 Revision History: 6-Jan-1999 VladS created --*/ #ifndef _INFOSET_H_ #define _INFOSET_H_ #include #include #include #include class DEVICE_INFOSET { public: DEVICE_INFOSET(IN GUID guidClass) { m_DeviceInfoSet = NULL; m_ClassGuid = guidClass; Initialize(); m_fValid = TRUE; } ~DEVICE_INFOSET( VOID ) { Reset(); } inline BOOL IsValid( VOID ) { return(m_fValid); } inline void EnterCrit(VOID) { m_dwCritSec.Lock(); } inline void LeaveCrit(VOID) { m_dwCritSec.Unlock(); } inline HDEVINFO QueryInfoSetHandle(VOID) { return(m_DeviceInfoSet); } // // Initialize info set for given class // BOOL Initialize(VOID) { HDEVINFO NewDeviceInfoSet; DWORD dwErr; m_DeviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL); Refresh(); #ifdef DEBUG Dump(); #endif return (TRUE); } BOOL Refresh(VOID) { HDEVINFO NewDeviceInfoSet; DWORD dwErr; if ( m_DeviceInfoSet && (m_DeviceInfoSet != INVALID_HANDLE_VALUE)) { #ifdef WINNT // // Now we can retrieve the existing list of active device // interfaces into the device information set we created above. // NewDeviceInfoSet = SetupDiGetClassDevsEx(&(m_ClassGuid), NULL, NULL, // DIGCF_PRESENT | DIGCF_DEVICEINTERFACE, DIGCF_DEVICEINTERFACE, m_DeviceInfoSet, NULL, NULL ); NewDeviceInfoSet = SetupDiGetClassDevsEx(&(m_ClassGuid), NULL, NULL, // DIGCF_PRESENT | DIGCF_DEVICEINTERFACE, 0, NewDeviceInfoSet, NULL, NULL ); if (NewDeviceInfoSet == INVALID_HANDLE_VALUE) { dwErr = ::GetLastError(); DBG_ERR(("SetupDiGetClassDevsEx failed with 0x%lx\n", dwErr)); return (FALSE); } #else // // BUGBUG // #pragma message("Rewrite for Win98") return (FALSE); #endif // // If SetupDiGetClassDevsEx succeeds and it was passed in an // existing device information set to be used, then the HDEVINFO // it returns is the same as the one it was passed in. Thus, we // can just use the original DeviceInfoSet handle from here on. // } return (TRUE); } // // // BOOL Reset(VOID) { SetupDiDestroyDeviceInfoList(m_DeviceInfoSet); return (TRUE); } // // Look up driver name by interface name // BOOL LookupDriverNameFromInterfaceName( LPCTSTR pszInterfaceName, StiCString* pstrDriverName ) { BUFFER bufDetailData; SP_DEVINFO_DATA spDevInfoData; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetailData; TCHAR szDevDriver[STI_MAX_INTERNAL_NAME_LENGTH]; DWORD cbData; DWORD dwErr; HKEY hkDevice = (HKEY)INVALID_HANDLE_VALUE; LONG lResult = ERROR_SUCCESS; DWORD dwType = REG_SZ; BOOL fRet = FALSE; BOOL fDataAcquired = FALSE; bufDetailData.Resize(sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(TCHAR) + 16 ); pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) bufDetailData.QueryPtr(); if (!pspDevInterfaceDetailData) { return (CR_OUT_OF_MEMORY); } // // Locate this device interface in our device information set. // spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); if (SetupDiOpenDeviceInterface(m_DeviceInfoSet, pszInterfaceName, DIODI_NO_ADD, &spDevInterfaceData)) { // // First try to open interface regkey. // hkDevice = SetupDiOpenDeviceInterfaceRegKey(m_DeviceInfoSet, &spDevInterfaceData, 0, KEY_READ); if(INVALID_HANDLE_VALUE != hkDevice){ *szDevDriver = TEXT('\0'); cbData = sizeof(szDevDriver); lResult = RegQueryValueEx(hkDevice, REGSTR_VAL_DEVICE_ID, NULL, &dwType, (LPBYTE)szDevDriver, &cbData); dwErr = ::GetLastError(); RegCloseKey(hkDevice); hkDevice = (HKEY)INVALID_HANDLE_VALUE; if(ERROR_SUCCESS == lResult){ fDataAcquired = TRUE; } // if(ERROR_SUCCESS == lResult) } // if(INVALID_HANDLE_VALUE != hkDevice) if(!fDataAcquired){ // // Try to open devnode regkey. // cbData = 0; pspDevInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); fRet = SetupDiGetDeviceInterfaceDetail(m_DeviceInfoSet, &spDevInterfaceData, pspDevInterfaceDetailData, bufDetailData.QuerySize(), &cbData, &spDevInfoData); if(fRet){ // // Get device interface registry key. // hkDevice = SetupDiOpenDevRegKey(m_DeviceInfoSet, &spDevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ); dwErr = ::GetLastError(); } else { DBG_ERR(("SetupDiGetDeviceInterfaceDetail() Failed Err=0x%x",GetLastError())); } if (INVALID_HANDLE_VALUE != hkDevice) { *szDevDriver = TEXT('\0'); cbData = sizeof(szDevDriver); lResult = RegQueryValueEx(hkDevice, REGSTR_VAL_DEVICE_ID, NULL, &dwType, (LPBYTE)szDevDriver, &cbData); dwErr = ::GetLastError(); RegCloseKey(hkDevice); hkDevice = (HKEY)INVALID_HANDLE_VALUE; if(ERROR_SUCCESS == lResult){ fDataAcquired = TRUE; } // if(ERROR_SUCCESS == lResult) } else { // if (INVALID_HANDLE_VALUE != hkDevice) DBG_ERR(("SetupDiOpenDevRegKey() Failed Err=0x%x",GetLastError())); fRet = FALSE; } // if (INVALID_HANDLE_VALUE != hkDevice) } // if(!fDataAcquired) if (fDataAcquired) { // Got it pstrDriverName->CopyString(szDevDriver); fRet = TRUE; } // if (fDataAcquired) } else { DBG_ERR(("SetupDiOpenDeviceInterface() Failed Err=0x%x",GetLastError())); fRet = FALSE; } return (fRet); } // // Look up device info data by driver name // BOOL LookupDeviceInfoFromDriverName( LPCTSTR pszDriverName, StiCString* pstrInterfaceName, DEVINST*pDeviceInstance = NULL ) { SP_DEVINFO_DATA spDevInfoData; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetailData; BUFFER bufDetailData; TCHAR szDevDriver[STI_MAX_INTERNAL_NAME_LENGTH]; ULONG cbData; CONFIGRET cmRet = CR_NO_SUCH_DEVINST; DWORD dwRequired; DWORD Idx; DWORD dwError; DWORD dwType; BOOL fRet = FALSE; BOOL fFoundMatch = FALSE; LONG lResult = ERROR_SUCCESS; HKEY hkDevice = (HKEY)INVALID_HANDLE_VALUE; Refresh(); dwRequired = 0; ZeroMemory(&spDevInterfaceData,sizeof(spDevInterfaceData)); bufDetailData.Resize(sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(TCHAR) + 16 ); pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) bufDetailData.QueryPtr(); if (!pspDevInterfaceDetailData) { ::SetLastError(ERROR_NOT_ENOUGH_MEMORY); return (FALSE); } if (m_DeviceInfoSet != INVALID_HANDLE_VALUE) { ZeroMemory(&spDevInfoData,sizeof(spDevInfoData)); spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA); spDevInfoData.ClassGuid = m_ClassGuid; pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) bufDetailData.QueryPtr(); for (Idx = 0; SetupDiEnumDeviceInfo (m_DeviceInfoSet, Idx, &spDevInfoData); Idx++) { // // Get driver name property // hkDevice = SetupDiOpenDevRegKey(m_DeviceInfoSet, &spDevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ); if(INVALID_HANDLE_VALUE != hkDevice){ *szDevDriver = TEXT('\0'); cbData = sizeof(szDevDriver); lResult = RegQueryValueEx(hkDevice, REGSTR_VAL_DEVICE_ID, NULL, &dwType, (LPBYTE)szDevDriver, &cbData); RegCloseKey(hkDevice); hkDevice = (HKEY)INVALID_HANDLE_VALUE; if(ERROR_SUCCESS == lResult){ if (lstrcmpi(pszDriverName,szDevDriver) == 0 ) { // // Get interface. // spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); spDevInterfaceData.InterfaceClassGuid = m_ClassGuid; fRet = SetupDiEnumDeviceInterfaces (m_DeviceInfoSet, &spDevInfoData, &(m_ClassGuid), 0, &spDevInterfaceData); if(!fRet){ DBG_ERR(("SetupDiEnumDeviceInterfaces() Failed Err=0x%x",GetLastError())); fFoundMatch = FALSE; continue; } // // Found match .. // fFoundMatch = TRUE; break; } // if (lstrcmpi(pszDriverName,szDevDriver) == 0 ) } //if(ERROR_SUCCESS == lResult) } // if(INVALID_HANDLE_VALUE != hkDevice) } // for (Idx = 0; SetupDiEnumDeviceInfo (m_DeviceInfoSet, Idx, &spDevInfoData); Idx++) if(!fFoundMatch){ // // Try to get interface regkey. // spDevInterfaceData.InterfaceClassGuid = m_ClassGuid; spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); for(Idx = 0; SetupDiEnumDeviceInterfaces (m_DeviceInfoSet, NULL, &m_ClassGuid, Idx, &spDevInterfaceData); Idx++) { hkDevice = SetupDiOpenDeviceInterfaceRegKey(m_DeviceInfoSet, &spDevInterfaceData, 0, KEY_READ); if(INVALID_HANDLE_VALUE != hkDevice){ *szDevDriver = TEXT('\0'); cbData = sizeof(szDevDriver); lResult = RegQueryValueEx(hkDevice, REGSTR_VAL_DEVICE_ID, NULL, &dwType, (LPBYTE)szDevDriver, &cbData); RegCloseKey(hkDevice); hkDevice = (HKEY)INVALID_HANDLE_VALUE; if(ERROR_SUCCESS == lResult){ if (lstrcmpi(pszDriverName,szDevDriver) == 0 ) { // // Found match .. // fFoundMatch = TRUE; break; } // if (lstrcmpi(pszDriverName,szDevDriver) == 0 ) } //if(ERROR_SUCCESS == lResult) } // if(INVALID_HANDLE_VALUE != hkDevice) } // for(Idx = 0; SetupDiEnumDeviceInterfaces (m_DeviceInfoSet, NULL, &m_ClassGuid, Idx, &spDevInterfaceData); Idx++) } // if(!fFoundMatch) if (fFoundMatch) { dwRequired = 0; pspDevInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); fRet = SetupDiGetDeviceInterfaceDetail(m_DeviceInfoSet, &spDevInterfaceData, pspDevInterfaceDetailData, bufDetailData.QuerySize(), &dwRequired, &spDevInfoData); dwError = ::GetLastError(); if (fRet) { pstrInterfaceName -> CopyString(pspDevInterfaceDetailData->DevicePath); fRet = TRUE; } else { // DPRINTF failed to get interface detail } } // if (fFoundMatch) } else { // DPRINTF - invalid dev info set handle } return (fRet); } // // Process refresh message // BOOL ProcessNewDeviceChangeMessage( IN LPARAM lParam ) { DWORD dwErr; PDEV_BROADCAST_DEVICEINTERFACE pDevBroadcastDeviceInterface; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; pDevBroadcastDeviceInterface = (PDEV_BROADCAST_DEVICEINTERFACE)lParam; // // Open this new device interface into our device information // set. // if (!SetupDiOpenDeviceInterface(m_DeviceInfoSet, pDevBroadcastDeviceInterface->dbcc_name, 0, NULL)) { dwErr = GetLastError(); } #ifdef DEBUG Dump(); #endif return (TRUE); } BOOL ProcessDeleteDeviceChangeMessage( IN LPARAM lParam ) { DBG_FN(ProcessDeleteDeviceChangeMessage); DWORD dwErr; PDEV_BROADCAST_DEVICEINTERFACE pDevBroadcastDeviceInterface; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; pDevBroadcastDeviceInterface = (PDEV_BROADCAST_DEVICEINTERFACE)lParam; // // First, locate this device interface in our device information // set. // spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); if (SetupDiOpenDeviceInterface(m_DeviceInfoSet, pDevBroadcastDeviceInterface->dbcc_name, DIODI_NO_ADD, &spDevInterfaceData)) { if (!SetupDiDeleteDeviceInterfaceData(m_DeviceInfoSet, &spDevInterfaceData)) { dwErr = GetLastError(); } } // Do we need to do refresh now ? BUGBUG Refresh(); #ifdef DEBUG Dump(); #endif return (TRUE); } VOID Dump(VOID) { SP_DEVINFO_DATA spDevInfoData; UINT Idx; ZeroMemory(&spDevInfoData,sizeof(spDevInfoData)); spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA); spDevInfoData.ClassGuid = m_ClassGuid; for (Idx = 0; SetupDiEnumDeviceInfo (m_DeviceInfoSet, Idx, &spDevInfoData); Idx++) { Idx = Idx; } } // DWORD m_dwSignature; private: BOOL m_fValid; CRIT_SECT m_dwCritSec; DWORD m_dwFlags; GUID m_ClassGuid; HDEVINFO m_DeviceInfoSet; }; // // Take device class // class TAKE_DEVICE_INFOSET { private: DEVICE_INFOSET* m_pInfoSet; public: inline TAKE_DEVICE_INFOSET(DEVICE_INFOSET* pInfoSet) : m_pInfoSet(pInfoSet) { m_pInfoSet->EnterCrit(); } inline ~TAKE_DEVICE_INFOSET() { m_pInfoSet->LeaveCrit(); } }; #endif // _INFOSET_H_