///////////////////////////////////////////////////////////////////////// // // Copyright (c) 1997-2002 Microsoft Corporation, All Rights Reserved // ///////////////////////////////////////////////////////////////////////// #include "precomp.h" #include #include "poormansresource.h" #include "resourcedesc.h" #include "irqdesc.h" #include #include "refptr.h" #include "cfgmgrdevice.h" #include "irqdesc.h" #include "iodesc.h" // don't need this yet #include "devdesc.h" // don't need this yet #include "dmadesc.h" #include #include "nt4svctoresmap.h" #include "chwres.h" #include "configmgrapi.h" #include // The Map we will use below is an STL Template, so make sure we have the std namespace // available to us. using namespace std; typedef ULONG (WINAPI *CIM16GetConfigManagerStatus)(LPSTR HardwareKey); //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::CConfigMgrDevice // // Class Constructor. // // Inputs: LPCTSTR pszConfigMgrName - Name of device in config // manager (HKEY_DYN_DATA\Config Manager\Enum // subkey). // // Outputs: None. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// CConfigMgrDevice::CConfigMgrDevice( LPCWSTR pszConfigMgrName,DWORD dwTypeToGet ) : CRefPtrLite(), m_strConfigMgrName( pszConfigMgrName ), m_strHardwareKey(), m_strDeviceDesc(), m_pbAllocationData( NULL ), m_dwSizeAllocationData( 0 ) { m_dwTypeToGet = dwTypeToGet; GetConfigMgrInfo(); GetDeviceInfo(); } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::CConfigMgrDevice // // Class Constructor. // // Inputs: DEVNODE m_dn - Device Node from tree // DWORD dwResType - Resource Types to Enum // // Outputs: None. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// CConfigMgrDevice::CConfigMgrDevice( DEVNODE dn, DWORD dwResType /*=ResType_All*/ ) : CRefPtrLite(), m_strConfigMgrName(), m_strHardwareKey(), m_strDeviceDesc(), m_pbAllocationData( NULL ), m_dwSizeAllocationData( 0 ), m_dn( dn ), m_dwTypeToGet( dwResType ) { } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::~CConfigMgrDevice // // Class Destructor. // // Inputs: None. // // Outputs: None. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// CConfigMgrDevice::~CConfigMgrDevice( void ) { if ( NULL != m_pbAllocationData ){ delete [] m_pbAllocationData; m_pbAllocationData = NULL; } } //////////////////////////////////////////////////////////////////////// // // This function searches for the configuration manager device name // based on the // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::MapKeyToConfigMgrDeviceName() { BOOL fRc = FALSE; CRegistrySearch Search; CHPtrArray chsaList; CHString *pPtr; Search.SearchAndBuildList( _T("Config Manager\\Enum"), chsaList, m_strConfigMgrName, _T("HardWareKey"), VALUE_SEARCH,HKEY_DYN_DATA ); if( chsaList.GetSize() > 0 ){ pPtr = ( CHString *) chsaList.GetAt(0); WCHAR szTmp[50]; szTmp[0] = _T('\0'); swscanf(*pPtr, L"Config Manager\\Enum\\%s", szTmp); m_strConfigMgrName = CHString(szTmp); fRc = TRUE; } Search.FreeSearchList( CSTRING_PTR, chsaList ); return fRc; } //////////////////////////////////////////////////////////////////////// #ifdef WIN9XONLY DWORD CConfigMgrDevice::GetStatusFromConfigManagerDirectly(void) { DWORD dwStatus = 0L; // thunk down to 16-bit to get it CCim32NetApi *t_pCim32Api = HoldSingleCim32NetPtr::GetCim32NetApiPtr(); if( t_pCim32Api) { dwStatus = (t_pCim32Api->GetWin9XConfigManagerStatus)((char*)(const char*)_bstr_t(m_strHardwareKey)); CResourceManager::sm_TheResourceManager.ReleaseResource(g_guidCim32NetApi, t_pCim32Api); t_pCim32Api = NULL; } return dwStatus; } #endif //////////////////////////////////////////////////////////////////////// // // This function translates the binary status code from the registry // into the following values: // OK, ERROR, DEGRADED, UNKNOWN // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetStatus(CHString & chsStatus) { DWORD dwStatus = 0L; BOOL fRc = FALSE; CRegistry Reg; CHString chsKey = CONFIGMGR_ENUM_KEY+m_strConfigMgrName; chsStatus = IDS_STATUS_Unknown; // Do this the old tried and true LEGACY way. Lose this code ASAP! if ( NULL == m_dn ) { #ifdef WIN9XONLY { if( !m_strHardwareKey.IsEmpty() ) { dwStatus = GetStatusFromConfigManagerDirectly(); } } #endif #ifdef NTONLY if( !m_strConfigMgrName.IsEmpty()) #endif { //=================================================== // Initialize //=================================================== if( Reg.Open(HKEY_DYN_DATA, chsKey, KEY_READ) == ERROR_SUCCESS ) { DWORD dwSize = 4; Reg.GetCurrentBinaryKeyValue(CONFIGMGR_DEVICE_STATUS_VALUE, (BYTE *)&dwStatus, &dwSize); } } } else { // Use the config manager to get the data for us GetStatus( &dwStatus, NULL ); } if( dwStatus != 0L ) { fRc = TRUE; //============================================== // OK, these are wild guesses at translation, // we may need to fiddle with these //============================================== if( dwStatus & DN_ROOT_ENUMERATED || dwStatus & DN_DRIVER_LOADED || dwStatus & DN_ENUM_LOADED || dwStatus & DN_STARTED ){ chsStatus = IDS_STATUS_OK; } // we don't care about these: // DN_MANUAL,DN_NOT_FIRST_TIME,DN_HARDWARE_ENUM,DN_FILTERED // DN_DISABLEABLE, DN_REMOVABLE,DN_MF_PARENT,DN_MF_CHILD // DN_NEED_TO_ENUM, DN_LIAR,DN_HAS_MARK if( dwStatus & DN_MOVED || dwStatus & DN_WILL_BE_REMOVED){ chsStatus = IDS_STATUS_Degraded; } if( dwStatus & DN_HAS_PROBLEM || dwStatus & DN_PRIVATE_PROBLEM){ chsStatus = IDS_STATUS_Error; } } return fRc; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetConfigMgrInfo // // Opens the appropriate Config Manager SubKey and loads values from // there. // // Inputs: None. // // Outputs: None. // // Return: TRUE/FALSE - Did we open the subkey and get the values // we wanted. // // Comments: Needs to be able to get read access to the registry. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetConfigMgrInfo( void ) { BOOL fReturn = FALSE; // For this to function correctly, we MUST have a value in // m_strConfigMgrName. if ( !m_strConfigMgrName.IsEmpty() ){ HKEY hConfigMgrKey = NULL; CHString strKeyName( CONFIGMGR_ENUM_KEY ); // Open the config manager key strKeyName += m_strConfigMgrName; // Don't forget to concat name Sanj, you big dummy if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_DYN_DATA, TOBSTRT(strKeyName), 0, KEY_READ, &hConfigMgrKey ) ) { ON_BLOCK_EXIT ( RegCloseKey, hConfigMgrKey ) ; // Get our hardware key, status and our resource allocation if ( GetHardwareKey( hConfigMgrKey ) ) { // Status is device status information from the registry. if ( GetStatusInfo( hConfigMgrKey ) ) { fReturn = GetResourceAllocation( hConfigMgrKey ); } } } } return FALSE; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetHardwareKey // // Gets the Config Manager HardwareKey value. // // Inputs: HKEY Key - Config Manager SubKey to open. // // Outputs: None. // // Return: TRUE/FALSE - Did we get the value. // // Comments: Needs to be able to get read access to the registry. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetHardwareKey( HKEY hKey ) { BOOL fReturn = FALSE; DWORD dwSizeHardwareKeyName = 0; // First, get the Hardware key name buffer size. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, CONFIGMGR_DEVICE_HARDWAREKEY_VALUE, 0, NULL, NULL, &dwSizeHardwareKeyName ) ) { m_strHardwareKey = L""; // We do it this way since CHString no longer changes types with TCHAR // LPTSTR pszBuffer = m_strHardwareKey.GetBuffer( dwSizeHardwareKeyName ); LPTSTR pszBuffer = new TCHAR[dwSizeHardwareKeyName]; //(LPTSTR) malloc(dwSizeHardwareKeyName * sizeof(TCHAR)); if ( NULL != pszBuffer ) { try { // Now get the real buffer if ( ERROR_SUCCESS == RegQueryValueEx( hKey, CONFIGMGR_DEVICE_HARDWAREKEY_VALUE, 0, NULL, (LPBYTE) pszBuffer, &dwSizeHardwareKeyName ) ) { fReturn = TRUE; m_strHardwareKey = pszBuffer; } } catch ( ... ) { delete [] pszBuffer; throw ; } delete [] pszBuffer; } else { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } // IF RegQueryValue Ex return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetResourceAllocation // // Gets the Config Manager Device Resource Allocation and fills // out the resource list as appropriate. // // Inputs: HKEY Key - Config Manager SubKey to open. // // Outputs: None. // // Return: TRUE/FALSE - Did we get the value. // // Comments: Must have read access to the registry. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetResourceAllocation( HKEY hKey ) { BOOL fReturn = FALSE; DWORD dwSizeAllocation = 0; // First, get the buffer size. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, CONFIGMGR_DEVICE_ALLOCATION_VALUE, 0, NULL, NULL, &dwSizeAllocation ) ) { // Initialize pbData, using a stack buffer if we can (most of the time // this will probably suffice). LPBYTE pbData = new BYTE[dwSizeAllocation]; // Just be safe here. if ( NULL != pbData ) { // Now get the real buffer if ( ERROR_SUCCESS == RegQueryValueEx( hKey, CONFIGMGR_DEVICE_ALLOCATION_VALUE, 0, NULL, pbData, &dwSizeAllocation ) ) { m_pbAllocationData = pbData; m_dwSizeAllocationData = dwSizeAllocation; fReturn = TRUE; } // DON'T delete the data buffer. The object destructor does it. // delete [] pbData; else { // MUST delete here though !!! delete [] pbData; } } else { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } // IF RegQueryValue Ex return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetStatusInfo // // Gets the Config Manager Device Status and Problem fields. // // Inputs: HKEY Key - Config Manager SubKey to open. // // Outputs: None. // // Return: TRUE/FALSE - Did we get the values. // // Comments: Must have read access to the registry. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetStatusInfo( HKEY hKey ) { BOOL fReturn = FALSE; DWORD dwBuffSize = sizeof(DWORD); // First, get the status value, then get the problem value. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, CONFIGMGR_DEVICE_STATUS_VALUET, 0, NULL, (LPBYTE) &m_dwStatus, &dwBuffSize ) ) { // Now get the problem dwBuffSize = sizeof(DWORD); if ( ERROR_SUCCESS == RegQueryValueEx( hKey, CONFIGMGR_DEVICE_PROBLEM_VALUE, 0, NULL, (LPBYTE) &m_dwProblem, &dwBuffSize ) ) { fReturn = TRUE; } } // IF RegQueryValue Ex return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetDeviceInfo // // Uses the HardwareKey value to get further device information. // // Inputs: None. // // Outputs: None. // // Return: TRUE/FALSE - Did we get the value(s). // // Comments: Needs to be able to get read access to the registry. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetDeviceInfo( void ) { BOOL fReturn = FALSE; // For this to function correctly, we MUST have a value in // m_strHardwareKey if ( !m_strHardwareKey.IsEmpty() ) { HKEY hDeviceKey = NULL; CHString strKeyName( LOCALMACHINE_ENUM_KEY ); // Open the config manager key strKeyName += m_strHardwareKey; // Don't forget to concat name Sanj, you big dummy if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, TOBSTRT(strKeyName), 0, KEY_READ, &hDeviceKey ) ) { ON_BLOCK_EXIT ( RegCloseKey, hDeviceKey ) ; fReturn = GetDeviceDesc( hDeviceKey ); } } return FALSE; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetDeviceDesc // // Gets the Device Description from the supplied subkey. // // Inputs: HKEY Key - Device SubKey to get info from. // // Outputs: None. // // Return: TRUE/FALSE - Did we get the value. // // Comments: If the value doesn't exist, this is not an error. We'll // just clear the value. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetDeviceDesc( HKEY hKey ) { BOOL fReturn = FALSE; DWORD dwSizeDeviceName = 0; LONG lReturn = 0L; // First, get the DeviceDesc buffer size. if ( ( lReturn = RegQueryValueEx( hKey, CONFIGMGR_DEVICEDESC_VALUE, 0, NULL, NULL, &dwSizeDeviceName ) ) == ERROR_SUCCESS ) { //LPTSTR pszBuffer = m_strDeviceDesc.GetBuffer( dwSizeDeviceName ); LPTSTR pszBuffer = new TCHAR[dwSizeDeviceName]; //(LPTSTR) malloc(dwSizeDeviceName * sizeof(TCHAR)); m_strDeviceDesc = L""; // Just be safe here. if ( NULL != pszBuffer ) { try { // Now get the real buffer if ( ( lReturn = RegQueryValueEx( hKey, CONFIGMGR_DEVICEDESC_VALUE, 0, NULL, (LPBYTE) pszBuffer, &dwSizeDeviceName ) ) == ERROR_SUCCESS ) { fReturn = TRUE; m_strDeviceDesc = pszBuffer; } else { fReturn = ( ERROR_FILE_NOT_FOUND == lReturn ); } } catch ( ... ) { delete [] pszBuffer; throw ; } //m_strDeviceDesc.ReleaseBuffer(); // Resets to string size delete [] pszBuffer; } else { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } // IF RegQueryValue Ex else { fReturn = ( ERROR_FILE_NOT_FOUND == lReturn ); } return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetIRQResources // // Walks the device's allocated resource configuration and fills out // an IRQ collection with IRQ Resources for this device. // // Inputs: CNT4ServiceToResourceMap* pResourceMap - For NT 4. // // Outputs: CIRQCollection& irqList - List to populate // // Return: TRUE/FALSE Error occured or not (empty list // is NOT an error). // // Comments: Requires READ Access to the data. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetIRQResources( CIRQCollection& irqList, CNT4ServiceToResourceMap *pResourceMap ) { BOOL fReturn = TRUE; CResourceCollection resourceList; // Clear the irq list first irqList.Empty(); // Populate the resource list first, specifying only IRQ resources, then we will // need to Dup the data into the irq list. If we go to an AddRef/Release model, we // will be able to copy pointers directly, saving time by not forcing us to // alloc and realloc data. if ( WalkAllocatedResources( resourceList, pResourceMap, ResType_IRQ ) ) { REFPTR_POSITION pos; if ( resourceList.BeginEnum( pos ) ) { CResourceDescriptorPtr pResource; // Check each resource, validating it is an IRQ before we cast. Because // the call to Walk should have filtered for us, these should be the // only resources returned. for ( pResource.Attach(resourceList.GetNext( pos )) ; pResource != NULL && fReturn ; pResource.Attach(resourceList.GetNext( pos )) ) { ASSERT_BREAK( pResource->GetResourceType() == ResType_IRQ ); if ( pResource->GetResourceType() == ResType_IRQ ) { // Cast the resource (we know the type) and add it to the // supplied list and we're done. (Ain't AddRef/Release easy?). CIRQDescriptor* pIRQ = (CIRQDescriptor*) pResource.GetInterfacePtr(); irqList.Add( pIRQ ); } // IF an IRQ Resource } // WHILE retrieving descriptors resourceList.EndEnum(); } // BeginEnum } // IF walked list return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetIOResources // // Walks the device's allocated resource configuration and fills out // an IO collection with IO Resources for this device. // // Inputs: CNT4ServiceToResourceMap* pResourceMap - For NT 4. // // Outputs: CIOCollection& IOList - List to populate // // Return: TRUE/FALSE Error occured or not (empty list // is NOT an error). // // Comments: Requires READ Access to the data. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetIOResources( CIOCollection& IOList, CNT4ServiceToResourceMap *pResourceMap ) { BOOL fReturn = TRUE; CResourceCollection resourceList; // Clear the IO list first IOList.Empty(); // Populate the resource list first, specifying only IO resources, then we will // need to Dup the data into the IO list. If we go to an AddRef/Release model, we // will be able to copy pointers directly, saving time by not forcing us to // alloc and realloc data. if ( WalkAllocatedResources( resourceList, pResourceMap, ResType_IO ) ) { REFPTR_POSITION pos; if ( resourceList.BeginEnum( pos ) ) { CResourceDescriptorPtr pResource; // Check each resource, validating it is an IO before we cast. Because // the call to Walk should have filtered for us, these should be the // only resources returned. for ( pResource.Attach(resourceList.GetNext( pos )) ; pResource != NULL && fReturn ; pResource.Attach(resourceList.GetNext( pos )) ) { ASSERT_BREAK( pResource->GetResourceType() == ResType_IO ); if ( pResource->GetResourceType() == ResType_IO ) { // Cast the resource (we know the type) and add it to the // supplied list and we're done. (Ain't AddRef/Release easy?). CIODescriptor* pIO = (CIODescriptor*) pResource.GetInterfacePtr(); IOList.Add( pIO ); } // IF an IO Resource } // WHILE retrieving descriptors resourceList.EndEnum(); } // BeginEnum() } // IF walked list return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetDMAResources // // Walks the device's allocated resource configuration and fills out // an DMA collection with DMA Resources for this device. // // Inputs: CNT4ServiceToResourceMap* pResourceMap - For NT 4. // // Outputs: CDMACollection& DMAList - List to populate // // Return: TRUE/FALSE Error occured or not (empty list // is NOT an error). // // Comments: Requires READ Access to the data. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetDMAResources( CDMACollection& DMAList, CNT4ServiceToResourceMap *pResourceMap ) { BOOL fReturn = TRUE; CResourceCollection resourceList; // Clear the DMA list first DMAList.Empty(); // Populate the resource list first, specifying only DMA resources, then we will // need to Dup the data into the DMA list. If we go to an AddRef/Release model, we // will be able to copy pointers directly, saving time by not forcing us to // alloc and realloc data. if ( WalkAllocatedResources( resourceList, pResourceMap, ResType_DMA ) ) { REFPTR_POSITION pos; if ( resourceList.BeginEnum( pos ) ) { CResourceDescriptorPtr pResource; // Check each resource, validating it is an DMA before we cast. Because // the call to Walk should have filtered for us, these should be the // only resources returned. for ( pResource.Attach(resourceList.GetNext( pos )) ; pResource != NULL && fReturn ; pResource.Attach(resourceList.GetNext( pos )) ) { ASSERT_BREAK( pResource->GetResourceType() == ResType_DMA ); if ( pResource->GetResourceType() == ResType_DMA ) { // Cast the resource (we know the type) and add it to the // supplied list and we're done. (Ain't AddRef/Release easy?). CDMADescriptor* pDMA = (CDMADescriptor*) pResource.GetInterfacePtr(); DMAList.Add( pDMA ); } // IF an DMA Resource } // WHILE retrieving descriptors resourceList.EndEnum(); } // BeginEnum } // IF walked list return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetDeviceMemoryResources // // Walks the device's allocated resource configuration and fills out // an DeviceMemory collection with DeviceMemory Resources for this device. // // Inputs: CNT4ServiceToResourceMap* pResourceMap - For NT 4. // // Outputs: CDeviceMemoryCollection& DeviceMemoryList - List to populate // // Return: TRUE/FALSE Error occured or not (empty list // is NOT an error). // // Comments: Requires READ Access to the data. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetDeviceMemoryResources( CDeviceMemoryCollection& DeviceMemoryList, CNT4ServiceToResourceMap *pResourceMap ) { BOOL fReturn = TRUE; CResourceCollection resourceList; // Clear the DeviceMemory list first DeviceMemoryList.Empty(); // Populate the resource list first, specifying only DeviceMemory resources, then we will // need to Dup the data into the DeviceMemory list. If we go to an AddRef/Release model, we // will be able to copy pointers directly, saving time by not forcing us to // alloc and realloc data. if ( WalkAllocatedResources( resourceList, pResourceMap, ResType_Mem ) ) { REFPTR_POSITION pos; if ( resourceList.BeginEnum( pos ) ) { CResourceDescriptorPtr pResource; // Check each resource, validating it is an DeviceMemory before we cast. Because // the call to Walk should have filtered for us, these should be the // only resources returned. for ( pResource.Attach(resourceList.GetNext( pos )) ; pResource != NULL && fReturn ; pResource.Attach(resourceList.GetNext( pos )) ) { ASSERT_BREAK( pResource->GetResourceType() == ResType_Mem ); if ( pResource->GetResourceType() == ResType_Mem ) { // Cast the resource (we know the type) and add it to the // supplied list and we're done. (Ain't AddRef/Release easy?). CDeviceMemoryDescriptor* pDeviceMemory = (CDeviceMemoryDescriptor*) pResource.GetInterfacePtr();; DeviceMemoryList.Add( pDeviceMemory ); } // IF an DeviceMemory Resource } // WHILE retrieving descriptors resourceList.EndEnum(); } // BeginEnum } // IF walked list return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::WalkAllocatedResources // // Walks the device's allocated resource configuration and fills out // a resource collection with the appropriate data. // // Inputs: RESOURCEID resType - Types of resources // to return. // CNT4ServiceToResourceMap* pResourceMap - For NT 4. // // Outputs: CResourceCollection& resourceList - List to populate // // Return: TRUE/FALSE List found or not. // // Comments: Requires READ Access to the data. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::WalkAllocatedResources( CResourceCollection& resourceList, CNT4ServiceToResourceMap *pResourceMap, RESOURCEID resType ) { LOG_CONF LogConfig; RES_DES ResDes; CONFIGRET cr; BOOL fReturn = FALSE ; // Dump the resource list first resourceList.Empty(); // If we're on NT 4, we gotta march to the beat of a different // drummer. #ifdef NTONLY if ( IsWinNT4() ) { // Convert Resource Type from RESOURCEID to CM_RESOURCE_TYPE fReturn = WalkAllocatedResourcesNT4( resourceList, pResourceMap, RESOURCEIDToCM_RESOURCE_TYPE( resType ) ); } else #endif { CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { #ifdef NTONLY BOOL fIsNT5 = IsWinNT5(); #endif // Get the allocated Logical Configuration. From there, we can iterate resource descriptors // until we find an IRQ Descriptor. cr = CR_NO_MORE_LOG_CONF ; if ( ( pconfigmgr->CM_Get_First_Log_Conf( &LogConfig, m_dn, ALLOC_LOG_CONF ) == CR_SUCCESS || pconfigmgr->CM_Get_First_Log_Conf( &LogConfig, m_dn, BOOT_LOG_CONF ) == CR_SUCCESS ) ) { cr = CR_SUCCESS ; RESOURCEID resID; // To get the first Resource Descriptor, we pass in the logical configuration. // The config manager knows how to handle this (or at least that's what the // ahem-"documentation" sez. RES_DES LastResDes = LogConfig; do { // Get only resources of the type we were made to retrieve cr = pconfigmgr->CM_Get_Next_Res_Des( &ResDes, LastResDes, resType, &resID, 0 ); // Clean up the prior resource descriptor handle if ( LastResDes != LogConfig ) { pconfigmgr->CM_Free_Res_Des_Handle( LastResDes ); } if ( CR_SUCCESS == cr ) { // CAUTION! On NT5, if we are doing a resource Type that is NOT ResType_All, // the OS does not appear to fill out ResID. I guess the assumption being // that we already know the resource type we are trying to get. HOWEVER, // if any bits like ResType_Ignored are set, NT 5 appears to be smartly // dropping those resources, so we'll just set resID here as if the // call on NT 5 had done anything. #ifdef NTONLY if ( ResType_All != resType && fIsNT5 ) { resID = resType; } #endif ULONG ulDataSize = 0; if ( CR_SUCCESS == ( cr = pconfigmgr->CM_Get_Res_Des_Data_Size( &ulDataSize, ResDes, 0 ) ) ) { ulDataSize += 10; // Pad for 10 bytes of safety BYTE* pbData = new BYTE[ulDataSize]; if ( NULL != pbData ) { try { cr = pconfigmgr->CM_Get_Res_Des_Data( ResDes, pbData, ulDataSize, 0 ); if ( CR_SUCCESS == cr ) { if ( !AddResourceToList( resID, pbData, ulDataSize, resourceList ) ) { cr = CR_OUT_OF_MEMORY; } } } catch ( ... ) { delete [] pbData; throw ; } // We're done with the data delete [] pbData; } // IF NULL != pbData else { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } // IF Get Data Size // Store the last descriptor, so we can go on to the next one. LastResDes = ResDes; } // If we got a descriptor } while ( CR_SUCCESS == cr ); // If we blew out on this, we're okay, since the error means we ran out of // resource descriptors. if ( CR_NO_MORE_RES_DES == cr ) { cr = CR_SUCCESS; } // Clean up the logical configuration handle pconfigmgr->CM_Free_Log_Conf_Handle( LogConfig ); } // IF got alloc logconf fReturn = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } } // else !NT 4 return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::AddResourceToList // // Copies resource data as necessary, coercing from 16 to 32 bit as // necessary, then adds the resource to the supplied list. // // Inputs: RESOURCEID resourceID - What resource is this? // LPVOID pResource - The resource // DWORD dwResourceLength - How long is it? // // Outputs: CResourceCollection& resourceList - List to populate // // Return: TRUE/FALSE Add succeeded or failed. // // Comments: None. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::AddResourceToList( RESOURCEID resourceID, LPVOID pResource, DWORD dwResourceLength, CResourceCollection& resourceList ) { IRQ_DES irqDes; IOWBEM_DES ioDes; DMA_DES dmaDes; MEM_DES memDes; // Don't know if Config Manager will return a resource ignored value, // so what we'll do here is check if the ignored bit is set, and for // now, ASSERT //ASSERT_BREAK( !(resourceID & ResType_Ignored_Bit) ); // Filter out extraneous bits RESOURCEID resType = ( resourceID & RESOURCE_TYPE_MASK ); // Hey, I'm an optimist BOOL fReturn = TRUE; // Different structures for 32/16 bit CFGMGR, so if // we ain't on WINNT, we need to coerce the data into // a proper structure. #ifdef WIN9XONLY { // We have to cheat here and coerce the data from a 16-bit // structure into a matching 32-bit structure. switch ( resType ) { case ResType_IRQ: { IRQDes16To32( (PIRQ_DES16) pResource, &irqDes ); } break; case ResType_IO: { IODes16To32( (PIO_DES16) pResource, &ioDes ); } break; case ResType_DMA: { DMADes16To32( (PDMA_DES16) pResource, &dmaDes ); } break; case ResType_Mem: { MEMDes16To32( (PMEM_DES16) pResource, &memDes ); } break; } // switch ResourceID } // IF !IsWinNT #endif #ifdef NTONLY { // Just copy the resource data into the appropriate descriptor switch ( resType ) { case ResType_IRQ: { CopyMemory( &irqDes, pResource, sizeof(IRQ_DES) ); } break; case ResType_IO: { // Because 16-bit has values 32-bit does not, we cheated and came up with our // own structure. 32-bit values are at the top, so zero out the struct and // trhe other values will just be ignored...yeah, that's the ticket. ZeroMemory( &ioDes, sizeof(ioDes) ); CopyMemory( &ioDes, pResource, sizeof(IO_DES) ); } break; case ResType_DMA: { CopyMemory( &dmaDes, pResource, sizeof(DMA_DES) ); } break; case ResType_Mem: { CopyMemory( &memDes, pResource, sizeof(MEM_DES) ); } break; } // SWITCH ResourceId } // else IsWinNT #endif CResourceDescriptorPtr pResourceDescriptor; // Just copy the resource data into the appropriate descriptor bool bAdd = true; switch ( resType ) { case ResType_IRQ: { pResourceDescriptor.Attach( (CResourceDescriptor*) new CIRQDescriptor( resourceID, irqDes, this ) ); } break; case ResType_IO: { bAdd = (ioDes).IOD_Alloc_End >= (ioDes).IOD_Alloc_Base; pResourceDescriptor.Attach ( (CResourceDescriptor*) new CIODescriptor( resourceID, ioDes, this ) ); } break; case ResType_DMA: { pResourceDescriptor.Attach ( (CResourceDescriptor*) new CDMADescriptor( resourceID, dmaDes, this ) ); } break; case ResType_Mem: { pResourceDescriptor.Attach ( (CResourceDescriptor*) new CDeviceMemoryDescriptor( resourceID, memDes, this ) ); } break; default: { // We don't know what it is, but make a raw one anyway pResourceDescriptor.Attach ( new CResourceDescriptor( resourceID, pResource, dwResourceLength, this ) ); } break; } // SWITCH ResourceId if (bAdd) { if ( NULL != pResourceDescriptor ) { fReturn = resourceList.Add( pResourceDescriptor ); } else { fReturn = FALSE; } } else { fReturn = TRUE; } return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::WalkAllocatedResourcesNT4 // // Because none of the logical configuration stuff in NT4 seems to // work worth a darn, we're gonna manhandle our own data from the // registry data under HKLM\HARDWARE\RESOURCEMAP. // // Inputs: CNT4ServiceToResourceMap* pResourceMap - Resource map // to use for the walk. We create // one if this is NULL. // CM_RESOURCE_TYPE resType - Resource Types to return. // // Outputs: CResourceCollection& resourceList - List to populate // // Return: TRUE/FALSE List found or not. // // Comments: Requires READ Access to the data. // //////////////////////////////////////////////////////////////////////// #ifdef NTONLY BOOL CConfigMgrDevice::WalkAllocatedResourcesNT4( CResourceCollection& resourceList, CNT4ServiceToResourceMap *pResourceMap, CM_RESOURCE_TYPE resType ) { BOOL fReturn = FALSE; CHString strServiceName; // Allocate a map if we need one. Otherwise use the one passed in that somebody // theoretically has cached off somewhere. CNT4ServiceToResourceMap* pLocalMap = pResourceMap; if ( NULL == pLocalMap ) { pLocalMap = new CNT4ServiceToResourceMap; } if ( NULL != pLocalMap ) { try { // Get our service name. If this succeeds, pull our resources from the reource map if ( GetService( strServiceName ) ) { fReturn = GetServiceResourcesNT4( strServiceName, *pLocalMap, resourceList, resType ); } } catch ( ... ) { if ( pLocalMap != pResourceMap ) { delete pLocalMap; } throw ; } // Clean up the local map if we allocated one if ( pLocalMap != pResourceMap ) { delete pLocalMap; } } else { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } return fReturn; } #endif #ifdef NTONLY BOOL CConfigMgrDevice::GetServiceResourcesNT4( LPCTSTR pszServiceName, CNT4ServiceToResourceMap& resourceMap, CResourceCollection& resourceList, CM_RESOURCE_TYPE cmrtFilter/*=CmResourceTypeNull*/ ) { BOOL fReturn = TRUE; LPRESOURCE_DESCRIPTOR pResourceDescriptor; // Iterate the resources, looking for matches against values we may be filtering // for. DWORD dwNumResources = resourceMap.NumServiceResources( pszServiceName ); for ( DWORD dwCtr = 0; dwCtr < dwNumResources && fReturn; dwCtr++ ) { pResourceDescriptor = resourceMap.GetServiceResource( pszServiceName, dwCtr ); // Grab the resource if it's our filter, or our filter is NULL, meaning grab everything if ( NULL != pResourceDescriptor && ( CmResourceTypeNull == cmrtFilter || cmrtFilter == pResourceDescriptor->CmResourceDescriptor.Type ) ) { CResourceDescriptorPtr pResource; // Perform appropriate type coercsions, and hook the resource into the resource /// list. switch ( pResourceDescriptor->CmResourceDescriptor.Type ) { case CmResourceTypeInterrupt: { IRQ_DES irqDes; NT4IRQToIRQ_DES( pResourceDescriptor, &irqDes ); pResource.Attach(new CIRQDescriptor( ResType_IRQ, irqDes, this ) ); } break; case CmResourceTypePort: { IOWBEM_DES ioDes; NT4IOToIOWBEM_DES( pResourceDescriptor, &ioDes ); pResource.Attach(new CIODescriptor( ResType_IO, ioDes, this ) ); } break; case CmResourceTypeMemory: { MEM_DES memDes; NT4MEMToMEM_DES( pResourceDescriptor, &memDes ); pResource.Attach(new CDeviceMemoryDescriptor( ResType_Mem, memDes, this )); } break; case CmResourceTypeDma: { DMA_DES dmaDes; NT4DMAToDMA_DES( pResourceDescriptor, &dmaDes ); pResource.Attach(new CDMADescriptor( ResType_DMA, dmaDes, this )); } break; // If it ain't one of these four, there ain't a whole heck of a // lot we're gonna do here } if ( NULL != pResource ) { fReturn = resourceList.Add( pResource ); } else { // We beefed on a simple memory allocation. Get out of here. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } // IF resource was one we wanted to handle } // FOR enum resources return fReturn; } #endif #ifdef NTONLY CM_RESOURCE_TYPE CConfigMgrDevice::RESOURCEIDToCM_RESOURCE_TYPE( RESOURCEID resType ) { CM_RESOURCE_TYPE cmResType = CmResourceTypeNull; switch ( resType ) { case ResType_All: cmResType = CmResourceTypeNull; break; case ResType_IO: cmResType = CmResourceTypePort; break; case ResType_IRQ: cmResType = CmResourceTypeInterrupt; break; case ResType_DMA: cmResType = CmResourceTypeDma; break; case ResType_Mem: cmResType = CmResourceTypeMemory; break; default: cmResType = CmResourceTypeNull; break; } return cmResType; } #endif #ifdef NTONLY void CConfigMgrDevice::NT4IRQToIRQ_DES( LPRESOURCE_DESCRIPTOR pResourceDescriptor, PIRQ_DES pirqDes32 ) { ZeroMemory( pirqDes32, sizeof(IRQ_DES) ); // 32-bit structure //typedef struct IRQ_Des_s { // DWORD IRQD_Count; // number of IRQ_RANGE structs in IRQ_RESOURCE // DWORD IRQD_Type; // size (in bytes) of IRQ_RANGE (IRQType_Range) // DWORD IRQD_Flags; // flags describing the IRQ (fIRQD flags) // ULONG IRQD_Alloc_Num; // specifies the IRQ that was allocated // ULONG IRQD_Affinity; //} IRQ_DES, *PIRQ_DES; pirqDes32->IRQD_Alloc_Num = pResourceDescriptor->CmResourceDescriptor.u.Interrupt.Level; pirqDes32->IRQD_Affinity = pResourceDescriptor->CmResourceDescriptor.u.Interrupt.Affinity; // We'll do our best on the flags conversion. if ( CmResourceShareShared == pResourceDescriptor->CmResourceDescriptor.ShareDisposition ) { pirqDes32->IRQD_Flags |= fIRQD_Share; } // Latched -> Edge? Have no idea, the other value in either case was Level, // so here's a leap of faith. if ( pResourceDescriptor->CmResourceDescriptor.Flags & CM_RESOURCE_INTERRUPT_LATCHED ) { pirqDes32->IRQD_Flags |= fIRQD_Edge; } } #endif #ifdef NTONLY void CConfigMgrDevice::NT4IOToIOWBEM_DES( LPRESOURCE_DESCRIPTOR pResourceDescriptor, PIOWBEM_DES pioDes32 ) { ZeroMemory( pioDes32, sizeof(IOWBEM_DES) ); // 32-bit structure //typedef struct _IOWBEM_DES{ // DWORD IOD_Count; // number of IO_RANGE structs in IO_RESOURCE // DWORD IOD_Type; // size (in bytes) of IO_RANGE (IOType_Range) // DWORDLONG IOD_Alloc_Base; // base of allocated port range // DWORDLONG IOD_Alloc_End; // end of allocated port range // DWORD IOD_DesFlags; // flags relating to allocated port range // BYTE IOD_Alloc_Alias; // From 16-bit-land // BYTE IOD_Alloc_Decode; // From 16-bit-land //} IOWBEM_DES; LARGE_INTEGER liTemp; // Used to avoid 64bit alignment problems liTemp.HighPart = pResourceDescriptor->CmResourceDescriptor.u.Port.Start.HighPart; liTemp.LowPart = pResourceDescriptor->CmResourceDescriptor.u.Port.Start.LowPart; pioDes32->IOD_Alloc_Base = liTemp.QuadPart; pioDes32->IOD_Alloc_End = pioDes32->IOD_Alloc_Base + ( pResourceDescriptor->CmResourceDescriptor.u.Port.Length - 1); // Don't know what to do with Share disposition here, since CFGMGR32 doesn't seem to // do it for IO Ports. //if ( CmResourceShareShared == pResourceDescriptor->CmResourceDescriptor.ShareDisposition ) //{ // pioDes32->IOD_Flags |= fIRQD_Share; //} // // Port Type flags convert straight across // //#define fIOD_PortType (0x1) // Bitmask,whether port is IO or memory //#define fIOD_Memory (0x0) // Port resource really uses memory //#define fIOD_IO (0x1) // Port resource uses IO ports //#define CM_RESOURCE_PORT_MEMORY 0 //#define CM_RESOURCE_PORT_IO 1 pioDes32->IOD_DesFlags = pResourceDescriptor->CmResourceDescriptor.Flags; } #endif #ifdef NTONLY void CConfigMgrDevice::NT4MEMToMEM_DES( LPRESOURCE_DESCRIPTOR pResourceDescriptor, PMEM_DES pmemDes32 ) { ZeroMemory( pmemDes32, sizeof(MEM_DES) ); // 32-bit structure //typedef struct Mem_Des_s { // DWORD MD_Count; // number of MEM_RANGE structs in MEM_RESOURCE // DWORD MD_Type; // size (in bytes) of MEM_RANGE (MType_Range) // DWORDLONG MD_Alloc_Base; // base memory address of range allocated // DWORDLONG MD_Alloc_End; // end of allocated range // DWORD MD_Flags; // flags describing allocated range (fMD flags) // DWORD MD_Reserved; //} MEM_DES, *PMEM_DES; LARGE_INTEGER liTemp; // Used to avoid 64bit alignment problems liTemp.HighPart = pResourceDescriptor->CmResourceDescriptor.u.Memory.Start.HighPart; liTemp.LowPart = pResourceDescriptor->CmResourceDescriptor.u.Memory.Start.LowPart; pmemDes32->MD_Alloc_Base = liTemp.QuadPart; pmemDes32->MD_Alloc_End = pmemDes32->MD_Alloc_Base + ( pResourceDescriptor->CmResourceDescriptor.u.Memory.Length - 1); // Don't know what to do with Share disposition here, since CFGMGR32 doesn't seem to // do it for IO Ports. //if ( CmResourceShareShared == pResourceDescriptor->CmResourceDescriptor.ShareDisposition ) //{ // pioDes32->MD_Flags |= fIRQD_Share; //} // Flag conversions I can do if ( pResourceDescriptor->CmResourceDescriptor.Flags & CM_RESOURCE_MEMORY_READ_WRITE ) { pmemDes32->MD_Flags |= fMD_RAM; pmemDes32->MD_Flags |= fMD_ReadAllowed; } else if ( pResourceDescriptor->CmResourceDescriptor.Flags & CM_RESOURCE_MEMORY_READ_ONLY ) { pmemDes32->MD_Flags |= fMD_ROM; pmemDes32->MD_Flags |= fMD_ReadAllowed; } else if ( pResourceDescriptor->CmResourceDescriptor.Flags & CM_RESOURCE_MEMORY_WRITE_ONLY ) { pmemDes32->MD_Flags |= fMD_RAM; pmemDes32->MD_Flags |= fMD_ReadDisallowed; } if ( pResourceDescriptor->CmResourceDescriptor.Flags & CM_RESOURCE_MEMORY_PREFETCHABLE ) { pmemDes32->MD_Flags |= fMD_PrefetchAllowed; } // Don't know what to do with these flags: //#define mMD_32_24 (0x2) // Bitmask, memory is 24 or 32-bit //#define fMD_32_24 mMD_32_24 // compatibility //#define fMD_24 (0x0) // Memory range is 24-bit //#define fMD_32 (0x2) // Memory range is 32-bit //#define mMD_CombinedWrite (0x10) // Bitmask,supports write-behind //#define fMD_CombinedWrite mMD_CombinedWrite // compatibility //#define fMD_CombinedWriteDisallowed (0x0) // no combined-write caching //#define fMD_CombinedWriteAllowed (0x10) // supports combined-write caching //#define mMD_Cacheable (0x20) // Bitmask,whether memory is cacheable //#define fMD_NonCacheable (0x0) // Memory range is non-cacheable //#define fMD_Cacheable (0x20) // Memory range is cacheable } #endif #ifdef NTONLY void CConfigMgrDevice::NT4DMAToDMA_DES( LPRESOURCE_DESCRIPTOR pResourceDescriptor, PDMA_DES pdmaDes32 ) { ZeroMemory( pdmaDes32, sizeof(DMA_DES) ); // 32-bit structure //typedef struct DMA_Des_s { // DWORD DD_Count; // number of DMA_RANGE structs in DMA_RESOURCE // DWORD DD_Type; // size (in bytes) of DMA_RANGE struct (DType_Range) // DWORD DD_Flags; // Flags describing DMA channel (fDD flags) // ULONG DD_Alloc_Chan; // Specifies the DMA channel that was allocated //} DMA_DES, *PDMA_DES; pdmaDes32->DD_Alloc_Chan = pResourceDescriptor->CmResourceDescriptor.u.Dma.Channel; // Don't know what to do with Share disposition here, since CFGMGR32 doesn't seem to // do it for IO Ports. //if ( CmResourceShareShared == pResourceDescriptor->CmResourceDescriptor.ShareDisposition ) //{ // pioDes32->MD_Flags |= fIRQD_Share; //} // These are possible flags for DMA, but I don't see any values from the // CHWRES.H file which make a sensible conversion to these values. // // Define the attribute flags for a DMA resource range. Each bit flag is // identified with a constant bitmask. Following the bitmask definition // are the possible values. // //#define mDD_Width (0x3) // Bitmask, width of the DMA channel: //#define fDD_BYTE (0x0) // 8-bit DMA channel //#define fDD_WORD (0x1) // 16-bit DMA channel //#define fDD_DWORD (0x2) // 32-bit DMA channel //#define fDD_BYTE_AND_WORD (0x3) // 8-bit and 16-bit DMA channel //#define mDD_BusMaster (0x4) // Bitmask, whether bus mastering is supported //#define fDD_NoBusMaster (0x0) // no bus mastering //#define fDD_BusMaster (0x4) // bus mastering //#define mDD_Type (0x18) // Bitmask, specifies type of DMA //#define fDD_TypeStandard (0x00) // standard DMA //#define fDD_TypeA (0x08) // Type-A DMA //#define fDD_TypeB (0x10) // Type-B DMA //#define fDD_TypeF (0x18) // Type-F DMA } #endif //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::IRQDes16To32 // // Coerces data from a 16-bit structure into a 32-bit structure. // // Inputs: PIRQ_DES16 pirqDes16 - 16-bit structure // // Outputs: PIRQ_DES pirqDes32 - 32-bit structure // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// void CConfigMgrDevice::IRQDes16To32( PIRQ_DES16 pirqDes16, PIRQ_DES pirqDes32 ) { ZeroMemory( pirqDes32, sizeof(IRQ_DES) ); // 16-bit Structure //struct IRQ_Des_s { // WORD IRQD_Flags; // WORD IRQD_Alloc_Num; // Allocated IRQ number // WORD IRQD_Req_Mask; // Mask of possible IRQs // WORD IRQD_Reserved; //}; // 32-bit structure //typedef struct IRQ_Des_s { // DWORD IRQD_Count; // number of IRQ_RANGE structs in IRQ_RESOURCE // DWORD IRQD_Type; // size (in bytes) of IRQ_RANGE (IRQType_Range) // DWORD IRQD_Flags; // flags describing the IRQ (fIRQD flags) // ULONG IRQD_Alloc_Num; // specifies the IRQ that was allocated // ULONG IRQD_Affinity; //} IRQ_DES, *PIRQ_DES; pirqDes32->IRQD_Alloc_Num = pirqDes16->IRQD_Alloc_Num; pirqDes32->IRQD_Flags = pirqDes16->IRQD_Flags; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::IODes16To32 // // Coerces data from a 16-bit structure into a 32-bit structure. // // Inputs: PIO_DES16 pioDes16 - 16-bit structure // // Outputs: PIOWBEM_DES pioDes32 - 32-bit structure // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// void CConfigMgrDevice::IODes16To32( PIO_DES16 pioDes16, PIOWBEM_DES pioDes32 ) { ZeroMemory( pioDes32, sizeof(IOWBEM_DES) ); // 16-bit structure //struct IO_Des_s { // WORD IOD_Count; // WORD IOD_Type; // WORD IOD_Alloc_Base; // WORD IOD_Alloc_End; // WORD IOD_DesFlags; // BYTE IOD_Alloc_Alias; // BYTE IOD_Alloc_Decode; //}; // 32-bit Structure //typedef struct _IOWBEM_DES{ // DWORD IOD_Count; // number of IO_RANGE structs in IO_RESOURCE // DWORD IOD_Type; // size (in bytes) of IO_RANGE (IOType_Range) // DWORDLONG IOD_Alloc_Base; // base of allocated port range // DWORDLONG IOD_Alloc_End; // end of allocated port range // DWORD IOD_DesFlags; // flags relating to allocated port range // BYTE IOD_Alloc_Alias; // From 16-bit-land // BYTE IOD_Alloc_Decode; // From 16-bit-land //} IOWBEM_DES; pioDes32->IOD_Count = pioDes16->IOD_Count; pioDes32->IOD_Type = pioDes16->IOD_Type; pioDes32->IOD_Alloc_Base = pioDes16->IOD_Alloc_Base; pioDes32->IOD_Alloc_End = pioDes16->IOD_Alloc_End; pioDes32->IOD_DesFlags = pioDes16->IOD_DesFlags; pioDes32->IOD_Alloc_Alias = pioDes16->IOD_Alloc_Alias; pioDes32->IOD_Alloc_Decode = pioDes16->IOD_Alloc_Decode; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::DMADes16To32 // // Coerces data from a 16-bit structure into a 32-bit structure. // // Inputs: PDMA_DES16 pdmaDes16 - 16-bit structure // // Outputs: PDMA_DES pdmaDes32 - 32-bit structure // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// void CConfigMgrDevice::DMADes16To32( PDMA_DES16 pdmaDes16, PDMA_DES pdmaDes32 ) { ZeroMemory( pdmaDes32, sizeof(DMA_DES) ); // 16-bit structure //struct DMA_Des_s { // BYTE DD_Flags; // BYTE DD_Alloc_Chan; // Channel number allocated // BYTE DD_Req_Mask; // Mask of possible channels // BYTE DD_Reserved; //}; // 32-bit structure //typedef struct DMA_Des_s { // DWORD DD_Count; // number of DMA_RANGE structs in DMA_RESOURCE // DWORD DD_Type; // size (in bytes) of DMA_RANGE struct (DType_Range) // DWORD DD_Flags; // Flags describing DMA channel (fDD flags) // ULONG DD_Alloc_Chan; // Specifies the DMA channel that was allocated //} DMA_DES, *PDMA_DES; pdmaDes32->DD_Flags = pdmaDes16->DD_Flags; pdmaDes32->DD_Alloc_Chan = pdmaDes16->DD_Alloc_Chan; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::MEMDes16To32 // // Coerces data from a 16-bit structure into a 32-bit structure. // // Inputs: PMEM_DES16 pmemDes16 - 16-bit structure // // Outputs: PMEM_DES pmemDes32 - 32-bit structure // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// void CConfigMgrDevice::MEMDes16To32( PMEM_DES16 pmemDes16, PMEM_DES pmemDes32 ) { ZeroMemory( pmemDes32, sizeof(MEM_DES) ); // 16-bit Structure //struct Mem_Des_s { // WORD MD_Count; // WORD MD_Type; // ULONG MD_Alloc_Base; // ULONG MD_Alloc_End; // WORD MD_Flags; // WORD MD_Reserved; //}; // 32-bit Structure //typedef struct Mem_Des_s { // DWORD MD_Count; // number of MEM_RANGE structs in MEM_RESOURCE // DWORD MD_Type; // size (in bytes) of MEM_RANGE (MType_Range) // DWORDLONG MD_Alloc_Base; // base memory address of range allocated // DWORDLONG MD_Alloc_End; // end of allocated range // DWORD MD_Flags; // flags describing allocated range (fMD flags) // DWORD MD_Reserved; //} MEM_DES, *PMEM_DES; pmemDes32->MD_Count = pmemDes16->MD_Count; pmemDes32->MD_Type = pmemDes16->MD_Type; pmemDes32->MD_Alloc_Base = pmemDes16->MD_Alloc_Base; pmemDes32->MD_Alloc_End = pmemDes16->MD_Alloc_End; pmemDes32->MD_Flags = pmemDes16->MD_Flags; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::TraverseAllocationData // // Traverses a block of data in order to determine // resource allocations for a particular device. // // Inputs: None. // // Outputs: CResourceCollection& resourceList - List to populate // // Return: None. // // Comments: Requires READ Access to the data. // //////////////////////////////////////////////////////////////////////// void CConfigMgrDevice::TraverseAllocationData( CResourceCollection& resourceList ) { const BYTE * pbTraverseData = m_pbAllocationData; DWORD dwSizeRemainingData = m_dwSizeAllocationData, dwResourceType = ResType_None, dwResourceSize = 0; // Clear the resource list first resourceList.Empty(); // OWCH! The first hack. Near as I can tell, we need to jump eight bytes in to get // to the first resource descriptor header (if there is one). TraverseData( pbTraverseData, dwSizeRemainingData, FIRST_RESOURCE_OFFSET ); // From here on, we only want to deal with known resource information. Use the // clever GetNextResource function to do all of our dirty work for us. If it // returns TRUE, then it's located a resource. Allocate the proper type of // descriptor based on type, place it in the list and go on to the next resource. while ( GetNextResource( pbTraverseData, dwSizeRemainingData, dwResourceType, dwResourceSize ) ) { if( dwResourceType == m_dwTypeToGet ){ PPOORMAN_RESDESC_HDR pResDescHdr = (PPOORMAN_RESDESC_HDR) pbTraverseData; CResourceDescriptorPtr pResDesc; // We have a valid type, however the actual resource descriptor will // lie SIZEOF_RESDESC_HDR bytes past where we're at now (pointing at // a resource header). switch ( dwResourceType ){ case ResType_Mem: { CDeviceMemoryDescriptor* pMemDesc = new CDeviceMemoryDescriptor( pResDescHdr, this ); pResDesc.Attach(pMemDesc); break; } case ResType_IO: { CIODescriptor* pIODesc = new CIODescriptor( pResDescHdr, this ); pResDesc.Attach(pIODesc); break; } case ResType_DMA: { CDMADescriptor* pDMADesc = new CDMADescriptor( pResDescHdr, this ); pResDesc.Attach(pDMADesc); break; } case ResType_IRQ: { CIRQDescriptor* pIRQDesc = new CIRQDescriptor( pResDescHdr, this ); pResDesc.Attach(pIRQDesc); break; } default: { pResDesc.Attach (new CResourceDescriptor( pResDescHdr, this )); } } // SWITCH // Give up if we have any failures, since they are most likely memory // related, and something really bad has happened. if ( NULL != pResDesc ) { if ( !resourceList.Add( pResDesc ) ) { break; } } else { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } // Move the pointer to the next resource descriptor header. TraverseData( pbTraverseData, dwSizeRemainingData, dwResourceSize ); } // WHILE finding new resources } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::FindNextResource // // Iterates through a block of data, hunting for byte patterns that // identify a resource type. In this case, as long as there are // SIZEOF_RESDESC_HDR bytes let to work with, we extract the resource // type and size and return those values for interpretation. // // Inputs: const BYTE* pbTraverseData - Data we are traversing. The // value will change as we progress through the // data. // DWORD dwSizeRemainingData - How much data remains to // be traversed. // // Outputs: DWORD& dwResourceType - What type of resource have we // found. // DWORD& dwResourceSize - How big the block of data // describing the resource is. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// BOOL CConfigMgrDevice::GetNextResource( const BYTE *pbTraverseData, DWORD dwSizeRemainingData, DWORD& dwResourceType, DWORD& dwResourceSize ) { BOOL fReturn = FALSE; // If we have less than SIZEOF_RESDESC_HDR bytes to work with, // give up, we ain't goin' nowhere. if ( dwSizeRemainingData > SIZEOF_RESDESC_HDR ) { PPOORMAN_RESDESC_HDR pResDescHdr = (PPOORMAN_RESDESC_HDR) pbTraverseData; DWORD dwResourceId = 0; dwResourceSize = pResDescHdr->dwResourceSize; // If we run into a zero byte header, the only value will be length, which // makes no sense, so we should probably just give up. if ( 0 != dwResourceSize ) { // See if it's one of the four standard types. If so, be aware that this code // ain't checking to see if it's ignored, and that an OEM can create a replacement // for one of these standard types, in which case strange and wondrous things // may happen. // Strip out any unwanted data, the first 5 bits are reserved for resource type // identification, so mask out everything else dwResourceType = pResDescHdr->dwResourceId; dwResourceType &= RESOURCE_TYPE_MASK; // We got a live one! fReturn = TRUE; } } // Return whether or not we found a resource return fReturn; } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::GetStatus // // Returns the status of the device as a string. If OK, it is "OK", if // we have a problem, it is "Error". // // Inputs: None. // // Outputs: CHString& str - String to place status in. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// void CConfigMgrDevice::GetProblem( CHString& str ) { // Save the string str = ( 0 == m_dwProblem ? IDS_CfgMgrDeviceStatus_OK : IDS_CfgMgrDeviceStatus_ERR ); } //////////////////////////////////////////////////////////////////////// // // Function: CConfigMgrDevice::TraverseData // // Helper function to safely bounce a pointer around our data. It will // jump the pointer by the specified amount, or the amount remaining, // whichever is smaller. // // Inputs: DWORD dwSizeTraverse - Size of upcoming jump. // // Outputs: const BYTE*& pbTraverseData - Data we are traversing. The // value will change as we progress through the // data. // DWORD& dwSizeRemainingData - How much data remains to // be traversed. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// void CConfigMgrDevice::TraverseData( const BYTE *& pbTraverseData, DWORD& dwSizeRemainingData, DWORD dwSizeTraverse ) { // Increment the pointer and reduce the size of remaining data, do this safely, not // traversing beyond the end of the remaining data, if that is all that is left. pbTraverseData += min( dwSizeRemainingData, dwSizeTraverse ); dwSizeRemainingData -= min( dwSizeRemainingData, dwSizeTraverse ); } // New functions that converse directly with the Config Manager APIs BOOL CConfigMgrDevice::GetDeviceID( CHString& strID ) { BOOL bRet = FALSE ; CONFIGRET cr = CR_SUCCESS; CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { char szDeviceId[MAX_DEVICE_ID_LEN+1]; ULONG ulBuffSize = 0; cr = pconfigmgr->CM_Get_Device_IDA( m_dn, szDeviceId, sizeof(szDeviceId), 0 ); if ( CR_SUCCESS == cr ) { strID = szDeviceId; } bRet = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } return bRet ; } BOOL CConfigMgrDevice::GetStatus( LPDWORD pdwStatus, LPDWORD pdwProblem ) { BOOL bRet = FALSE ; CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { DWORD dwStatus, dwProblem; CONFIGRET cr = pconfigmgr->CM_Get_DevNode_Status( &dwStatus, &dwProblem, m_dn, 0 ); // Perform pointer testing here. Ignore the man behind the curtain... if ( CR_SUCCESS == cr ) { if ( NULL != pdwStatus ) { *pdwStatus = dwStatus; } if ( NULL != pdwProblem ) { *pdwProblem = dwProblem; } } bRet = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } return bRet ; } BOOL CConfigMgrDevice::IsUsingForcedConfig() { BOOL bRet = FALSE ; LOG_CONF conf; CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { bRet = (pconfigmgr->CM_Get_First_Log_Conf(&conf, m_dn, FORCED_LOG_CONF) == CR_SUCCESS); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } return bRet ; } BOOL CConfigMgrDevice::GetParent( CConfigMgrDevicePtr & pParentDevice ) { BOOL bRet = FALSE ; CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; DEVNODE dn; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { CONFIGRET cr = pconfigmgr->CM_Get_Parent( &dn, m_dn, 0 ); if ( CR_SUCCESS == cr ) { CConfigMgrDevice* pDevice = new CConfigMgrDevice( dn ); pParentDevice.Attach(pDevice); } bRet = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } return bRet ; } BOOL CConfigMgrDevice::GetChild( CConfigMgrDevicePtr & pChildDevice ) { BOOL bRet = FALSE ; CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; DEVNODE dn; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { CONFIGRET cr = pconfigmgr->CM_Get_Child( &dn, m_dn, 0 ); if ( CR_SUCCESS == cr ) { CConfigMgrDevice* pDevice = new CConfigMgrDevice( dn ); pChildDevice.Attach(pDevice); } bRet = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } return bRet ; } BOOL CConfigMgrDevice::GetSibling( CConfigMgrDevicePtr & pSiblingDevice ) { BOOL bRet = FALSE ; CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; DEVNODE dn; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { CONFIGRET cr = pconfigmgr->CM_Get_Sibling( &dn, m_dn, 0 ); if ( CR_SUCCESS == cr ) { CConfigMgrDevice* pDevice = new CConfigMgrDevice( dn ); pSiblingDevice.Attach(pDevice); } bRet = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } return bRet ; } BOOL CConfigMgrDevice::GetStringProperty( ULONG ulProperty, CHString& strValue ) { TCHAR Buffer[REGSTR_VAL_MAX_HCID_LEN+1]; ULONG Type; ULONG Size = sizeof(Buffer); BOOL bRet = FALSE ; CONFIGRET cr = CR_SUCCESS; CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { if ( CR_SUCCESS == ( cr = pconfigmgr->CM_Get_DevNode_Registry_PropertyA( m_dn, ulProperty, &Type, Buffer, &Size, 0 ) ) ) { if ( REG_SZ == Type ) { strValue = Buffer; } else { cr = CR_WRONG_TYPE; } } bRet = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } return bRet ; } BOOL CConfigMgrDevice::GetDWORDProperty( ULONG ulProperty, DWORD *pdwVal ) { DWORD dwVal = 0; ULONG Type; ULONG Size = sizeof(DWORD); BOOL bRet = FALSE ; CONFIGRET cr = CR_SUCCESS; CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { if ( CR_SUCCESS == ( cr = pconfigmgr->CM_Get_DevNode_Registry_PropertyA( m_dn, ulProperty, &Type, &dwVal, &Size, 0 ) ) ) { #ifdef NTONLY { if ( REG_DWORD == Type ) { *pdwVal = dwVal; } else { cr = CR_WRONG_TYPE; } } #endif #ifdef WIN9XONLY { if ( REG_BINARY == Type ) // Apparently Win16 doesn't do REG_DWORD { *pdwVal = dwVal; } else { cr = CR_WRONG_TYPE; } } #endif } bRet = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } return bRet ; } BOOL CConfigMgrDevice::GetMULTISZProperty( ULONG ulProperty, CHStringArray& strArray ) { CONFIGRET cr = CR_SUCCESS; BOOL bRet = FALSE ; // No one is currently using this, so I'm not going to fix it now #ifdef DOESNT_WORK_FOR_UNICODE LPSTR pszStrings = NULL; ULONG Type; ULONG Size = 0; CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { if ( CR_SUCCESS == ( cr = pconfigmgr->CM_Get_DevNode_Registry_PropertyA( m_dn, ulProperty, &Type, pszStrings, &Size, 0 ) ) || CR_BUFFER_SMALL == cr ) { // SZ or MULTI_SZ is Okay (32-bit has MULTI_SZ values that are SZ in 16-bit) if ( REG_SZ == Type || REG_MULTI_SZ == Type ) { // Pad the string, but be aware that on NT4 I have seen situations in which // it reports less data than it actually returns (scary) Size += 32; pszStrings = new char[Size]; if ( NULL != pszStrings ) { try { // Clear out the memory to be especially safe. ZeroMemory( pszStrings, Size ); if ( CR_SUCCESS == ( cr = pconfigmgr->CM_Get_DevNode_Registry_PropertyA( m_dn, ulProperty, &Type, pszStrings, &Size, 0 ) ) ) { // For REG_SZ, add a single entry to the array if ( REG_SZ == Type ) { strArray.Add( pszStrings ); } else if ( REG_MULTI_SZ == Type ) { // Add strings to the array, watching out for the double NULL // terminator for the array LPSTR pszTemp = pszStrings; do { strArray.Add( pszTemp ); pszTemp += ( lstrlen( pszTemp ) + 1 ); } while ( NULL != *pszTemp ); } else { cr = CR_WRONG_TYPE; } } // If Got value } catch ( ... ) { delete [] pszStrings; throw ; } delete [] pszStrings; } // IF alloc pszStrings else { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } // IF REG_SZ or REG_MULTI_SZ else { cr = CR_WRONG_TYPE; } } // IF got size of entry bRet = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } #endif return bRet ; } BOOL CConfigMgrDevice::GetBusInfo( INTERFACE_TYPE *pitBusType, LPDWORD pdwBusNumber, CNT4ServiceToResourceMap *pResourceMap/*=NULL*/ ) { CMBUSTYPE busType = 0; ULONG ulSizeOfInfo = 0; PBYTE pbData = NULL; BOOL fReturn = FALSE; // Farm out to the appropriate handler #if NTONLY > 4 fReturn = GetBusInfoNT5( pitBusType, pdwBusNumber ); #endif #if NTONLY == 4 fReturn = GetBusInfoNT4( pitBusType, pdwBusNumber, pResourceMap ); #endif #ifdef WIN9XONLY { // Buffer for data. Should be big enough for any of the values we come across. BYTE abData[255]; ulSizeOfInfo = sizeof(abData); // Get the type and number. If the type is PCI, then get the PCI info, and this // will return a Bus Number value. If it returns a type other than PCI, then // we will assume a bus number of 0. CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { CONFIGRET cr = pconfigmgr->CM_Get_Bus_Info( m_dn, &busType, &ulSizeOfInfo, abData, 0 ); if ( CR_SUCCESS == cr ) { // Make sure we can convert from a 16-bit type to a known 32-bit type. // BusType_None will usually fail this, in which case we can call it // quits. if ( BusType16ToInterfaceType( busType, pitBusType ) ) { if ( BusType_PCI == busType ) { sPCIAccess *pPCIInfo = (sPCIAccess*) abData; *pdwBusNumber = pPCIInfo->bBusNumber; } else { *pdwBusNumber = 0; } } // IF 16-32bit conversion else { cr = CR_FAILURE; } } // CR_SUCCESS == cr fReturn = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } } // else !IsWinNT #endif return fReturn; } #if NTONLY > 4 // This is to hack around W2K problem where Cfg Mgr devices report they're // using Isa on boxes that have Eisa and not Isa. BOOL CConfigMgrDevice::IsIsaReallyEisa() { static bRet = -1; if (bRet == -1) { // FYI: This code based on code from motherboard.cpp. CRegistry regAdapters; CHString strPrimarySubKey; HRESULT hRc = WBEM_E_FAILED; DWORD dwPrimaryRc; // If anything below fails, we'll just assume Isa really is Isa. bRet = FALSE; //**************************************** // Open the registry //**************************************** if (regAdapters.OpenAndEnumerateSubKeys( HKEY_LOCAL_MACHINE, L"HARDWARE\\Description\\System", KEY_READ) == ERROR_SUCCESS) { BOOL bDone = FALSE, bIsaFound = FALSE, bEisaFound = FALSE; // Our goal is to find any subkey that has the string "Adapter" in // it and then read the "Identifier" value. for ( ; (!bIsaFound || !bEisaFound) && ((dwPrimaryRc = regAdapters.GetCurrentSubKeyName(strPrimarySubKey)) == ERROR_SUCCESS); regAdapters.NextSubKey()) { strPrimarySubKey.MakeUpper(); // If this is one of the keys we want since it has "Adapter" in // it then get the "Identifier" value. if (wcsstr(strPrimarySubKey, L"ADAPTER")) { WCHAR szKey[_MAX_PATH]; CRegistry reg; swprintf( szKey, L"%s\\%s", L"HARDWARE\\Description\\System", (LPCWSTR) strPrimarySubKey); if (reg.OpenAndEnumerateSubKeys( HKEY_LOCAL_MACHINE, szKey, KEY_READ) == ERROR_SUCCESS) { CHString strSubKey; // Enumerate the system components (like 0,1,...). for ( ; reg.GetCurrentSubKeyName(strSubKey) == ERROR_SUCCESS; reg.NextSubKey()) { CHString strBus; if (reg.GetCurrentSubKeyValue(L"Identifier", strBus) == ERROR_SUCCESS) { if (strBus == L"ISA") bIsaFound = TRUE; else if (strBus == L"EISA") bEisaFound = TRUE; } } } } } // If we found Eisa but not Isa, assume Cfg Mgr devices that report they're // using Isa are actually using Eisa. if (!bIsaFound && bEisaFound) bRet = TRUE; } } return bRet; } #endif #if NTONLY > 4 INTERFACE_TYPE CConfigMgrDevice::ConvertBadIsaBusType(INTERFACE_TYPE type) { if (type == Isa && IsIsaReallyEisa()) type = Eisa; return type; } #endif #if NTONLY > 4 BOOL CConfigMgrDevice::GetBusInfoNT5( INTERFACE_TYPE *pitBusType, LPDWORD pdwBusNumber ) { ULONG ulSizeOfInfo = 0; CONFIGRET cr; // Bus Number and Type are retrieved via the Registry function. This will only // work on NT 5. BOOL bRet = FALSE ; DWORD dwType = 0; DWORD dwBusNumber; INTERFACE_TYPE BusType; ulSizeOfInfo = sizeof(DWORD); CConfigMgrAPI* pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ; if ( pconfigmgr ) { if ( pconfigmgr->IsValid () ) { if ( CR_SUCCESS == ( cr = pconfigmgr->CM_Get_DevNode_Registry_PropertyA( m_dn, CM_DRP_BUSNUMBER, &dwType, &dwBusNumber, &ulSizeOfInfo, 0 ) ) ) { *pdwBusNumber = dwBusNumber; ulSizeOfInfo = sizeof(BusType); if ( CR_SUCCESS == ( cr = pconfigmgr->CM_Get_DevNode_Registry_PropertyA( m_dn, CM_DRP_LEGACYBUSTYPE, &dwType, &BusType, &ulSizeOfInfo, 0 ) ) ) { *pitBusType = ConvertBadIsaBusType(BusType); } // IF GetBusType } // IF GetBusNumber bRet = ( CR_SUCCESS == cr ); } CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, pconfigmgr ) ; } return bRet ; } #endif #if NTONLY == 4 BOOL CConfigMgrDevice::GetBusInfoNT4( INTERFACE_TYPE *pitBusType, LPDWORD pdwBusNumber, CNT4ServiceToResourceMap *pResourceMap ) { BOOL fReturn = FALSE; CHString strService; if ( GetService( strService ) ) { CNT4ServiceToResourceMap* pLocalMap = pResourceMap; // Instantiate a resource map if we need one. Then look for // resources for this service if ( NULL == pLocalMap ) { pLocalMap = new CNT4ServiceToResourceMap; } if ( NULL != pLocalMap ) { try { if ( 0 != pLocalMap->NumServiceResources( strService ) ) { LPRESOURCE_DESCRIPTOR pResource = pLocalMap->GetServiceResource( strService, 0 ); // If we got a resource, then use its BUS information directly to populate // our values. if ( NULL != pResource ) { fReturn = TRUE; *pitBusType = pResource->InterfaceType; *pdwBusNumber = pResource->Bus; } } // If there are resources for this service } catch ( ... ) { if ( pLocalMap != pResourceMap ) { delete pLocalMap; } throw ; } // Delete the local map if we allocated one. if ( pLocalMap != pResourceMap ) { delete pLocalMap; } } // if pLocalMap else { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } // If got service name return fReturn; } #endif BOOL CConfigMgrDevice::BusType16ToInterfaceType( CMBUSTYPE cmBusType16, INTERFACE_TYPE *pinterfaceType ) { BOOL fReturn = TRUE; // These are the enums defined for NT, so we'll standardize on these // // typedef enum Interface_Type { // Internal, // Isa, // Eisa, // MicroChannel, // TurboChannel, // PCIBus, // VMEBus, // NuBus, // PCMCIABus, // CBus, // MPIBus, // MPSABus, // MaximumInterfaceType // }INTERFACE_TYPE; // switch ( cmBusType16 ) { case BusType_ISA: { *pinterfaceType = Isa; } break; case BusType_EISA: { *pinterfaceType = Eisa; } break; case BusType_PCI: { *pinterfaceType = PCIBus; } break; case BusType_PCMCIA: { *pinterfaceType = PCMCIABus; } break; case BusType_ISAPNP: { // Closest match I could find *pinterfaceType = Isa; } break; case BusType_MCA: { *pinterfaceType = MicroChannel; } break; case BusType_BIOS: { *pinterfaceType = Internal; } break; default: { // Couldn't make the conversion (e.g. BusType_None) fReturn = FALSE; } } return fReturn; } // Registry Access functions. Sometimes we want to access the registry directly because // the device in question places private values in there that our regular functions cannot // access. BOOL CConfigMgrDevice::GetRegistryKeyName( CHString &strName) { CHString strDeviceID; BOOL bRet = TRUE; if ( GetDeviceID(strDeviceID) ) { // Build the correct key #ifdef NTONLY strName = _T("SYSTEM\\CurrentControlSet\\Enum\\"); #endif #ifdef WIN9XONLY strName = _T("Enum\\"); #endif strName += strDeviceID; } else { bRet = false; } return bRet; } // // Constructor and Destructor for the Device Collection // object. // //////////////////////////////////////////////////////////////////////// // // Function: CDeviceCollection::CDeviceCollection // // Class Constructor. // // Inputs: None. // // Outputs: None. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// CDeviceCollection::CDeviceCollection( void ) { } //////////////////////////////////////////////////////////////////////// // // Function: CDeviceCollection::~CDeviceCollection // // Class Destructor. // // Inputs: None. // // Outputs: None. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// CDeviceCollection::~CDeviceCollection( void ) { } BOOL CDeviceCollection::GetResourceList( CResourceCollection& resourceList ) { REFPTR_POSITION pos = NULL; CConfigMgrDevicePtr pDevice; CResourceCollection deviceresourceList; BOOL fReturn = TRUE; // Snapshot the resources on an NT 4 box. This only needs to happen once // and then we can pass this to devices to hook themselves up to the // appropriate resources. This keeps us from having to build this data // for each and every device. #ifdef NTONLY CNT4ServiceToResourceMap* pResourceMap = NULL; if ( IsWinNT4() ) { pResourceMap = new CNT4ServiceToResourceMap; } if (pResourceMap == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } try { #endif // Empty out the Resource List first resourceList.Empty(); if ( BeginEnum( pos ) ) { // Get the resource list from the device, then append it // to the list passed in to us. for ( pDevice.Attach(GetNext( pos ) ); pDevice != NULL; pDevice.Attach(GetNext( pos ) ) ) { #ifdef NTONLY pDevice->GetResourceList( deviceresourceList, pResourceMap ); #endif #ifdef WIN9XONLY pDevice->GetResourceList( deviceresourceList, NULL ); #endif resourceList.Append( deviceresourceList ); } // WHILE enuming devices EndEnum(); } else { fReturn = FALSE; } #ifdef NTONLY } catch ( ... ) { if ( NULL != pResourceMap ) { delete pResourceMap; } throw ; } // Clean up the resource map if we allocated one. if ( NULL != pResourceMap ) { delete pResourceMap; } #endif return fReturn; } BOOL CDeviceCollection::GetIRQResources( CIRQCollection& IRQList ) { REFPTR_POSITION pos = NULL; CConfigMgrDevicePtr pDevice; CIRQCollection deviceIRQList; BOOL fReturn = TRUE; // Snapshot the resources on an NT 4 box. This only needs to happen once // and then we can pass this to devices to hook themselves up to the // appropriate resources. This keeps us from having to build this data // for each and every device. CNT4ServiceToResourceMap* pResourceMap = NULL; #ifdef NTONLY if ( IsWinNT4() ) { pResourceMap = new CNT4ServiceToResourceMap; } if (pResourceMap == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } try { #endif // Empty out the IRQ List first IRQList.Empty(); if ( BeginEnum( pos ) ) { // For each device, get the IRQs and append them to the // supplied IRQ list for ( pDevice.Attach( GetNext( pos ) ); pDevice != NULL; pDevice.Attach( GetNext( pos ) )) { pDevice->GetIRQResources( deviceIRQList, pResourceMap ); IRQList.Append( deviceIRQList ); } // for all devices EndEnum(); } // Begin Enum else { fReturn = FALSE; } #ifdef NTONLY } catch ( ... ) { if ( NULL != pResourceMap ) { delete pResourceMap; } throw ; } // Clean up the resource map if we allocated one. if ( NULL != pResourceMap ) { delete pResourceMap; } #endif return fReturn; } BOOL CDeviceCollection::GetIOResources( CIOCollection& IOList ) { REFPTR_POSITION pos = NULL; CConfigMgrDevicePtr pDevice; CIOCollection deviceIOList; BOOL fReturn = TRUE; // Snapshot the resources on an NT 4 box. This only needs to happen once // and then we can pass this to devices to hook themselves up to the // appropriate resources. This keeps us from having to build this data // for each and every device. CNT4ServiceToResourceMap* pResourceMap = NULL; #ifdef NTONLY if ( IsWinNT4() ) { pResourceMap = new CNT4ServiceToResourceMap; } if (pResourceMap == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } try { #endif // Empty out the IO List first IOList.Empty(); if ( BeginEnum( pos ) ) { // For each device, get the IO Port List and append // it to the supplied list of IO Ports. for ( pDevice.Attach( GetNext( pos ) ); pDevice != NULL; pDevice.Attach( GetNext( pos ) )) { pDevice->GetIOResources( deviceIOList, pResourceMap ); IOList.Append( deviceIOList ); } // for all devices EndEnum(); } // BeginEnum else { fReturn = FALSE; } #ifdef NTONLY } catch ( ... ) { if ( NULL != pResourceMap ) { delete pResourceMap; } throw ; } // Clean up the resource map if we allocated one. if ( NULL != pResourceMap ) { delete pResourceMap; } #endif return fReturn; } BOOL CDeviceCollection::GetDMAResources( CDMACollection& DMAList ) { REFPTR_POSITION pos = NULL; CConfigMgrDevicePtr pDevice; CDMACollection deviceDMAList; BOOL fReturn = TRUE; // Snapshot the resources on an NT 4 box. This only needs to happen once // and then we can pass this to devices to hook themselves up to the // appropriate resources. This keeps us from having to build this data // for each and every device. CNT4ServiceToResourceMap* pResourceMap = NULL; #ifdef NTONLY if ( IsWinNT4() ) { pResourceMap = new CNT4ServiceToResourceMap; } if (pResourceMap == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } try { #endif // Empty out the DMA List first DMAList.Empty(); if ( BeginEnum( pos ) ) { // For each device, get the DMA resources and append them // to the supplied list of DMA resources for ( pDevice.Attach( GetNext( pos ) ); pDevice != NULL; pDevice.Attach( GetNext( pos ) )) { pDevice->GetDMAResources( deviceDMAList, pResourceMap ); DMAList.Append( deviceDMAList ); } // for all devices } // BeginEnum else { fReturn = FALSE; } #ifdef NTONLY } catch ( ... ) { if ( NULL != pResourceMap ) { delete pResourceMap; } throw ; } // Clean up the resource map if we allocated one. if ( NULL != pResourceMap ) { delete pResourceMap; } #endif return fReturn; } BOOL CDeviceCollection::GetDeviceMemoryResources( CDeviceMemoryCollection& DeviceMemoryList ) { REFPTR_POSITION pos = NULL; CConfigMgrDevicePtr pDevice; CDeviceMemoryCollection memoryList; BOOL fReturn = TRUE; // Snapshot the resources on an NT 4 box. This only needs to happen once // and then we can pass this to devices to hook themselves up to the // appropriate resources. This keeps us from having to build this data // for each and every device. CNT4ServiceToResourceMap* pResourceMap = NULL; #ifdef NTONLY if ( IsWinNT4() ) { pResourceMap = new CNT4ServiceToResourceMap; } if (pResourceMap == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } try { #endif // Empty out the DeviceMemory List first DeviceMemoryList.Empty(); if ( BeginEnum( pos ) ) { // For each device get the list of Memory Resources and // append it to the list of supplied Memory Resources. for ( pDevice.Attach( GetNext( pos ) ); pDevice != NULL; pDevice.Attach( GetNext( pos ) )) { pDevice->GetDeviceMemoryResources( memoryList, pResourceMap ); DeviceMemoryList.Append( memoryList ); } // for all devices EndEnum(); } // BeginEnum() else { fReturn = FALSE; } #ifdef NTONLY } catch ( ... ) { if ( NULL != pResourceMap ) { delete pResourceMap; } throw ; } // Clean up the resource map if we allocated one. if ( NULL != pResourceMap ) { delete pResourceMap; } #endif return fReturn; } #define MAX_DOS_DEVICES 8192 /***************************************************************************** * * FUNCTION : QueryDosDeviceNames * * DESCRIPTION : Queries for all Dos Device symbolic links * * INPUTS : none * * OUTPUTS : nichts * * RETURNS : nada * * COMMENTS : * *****************************************************************************/ BOOL WINAPI QueryDosDeviceNames ( TCHAR *&a_DosDeviceNameList ) { BOOL t_Status = FALSE ; BOOL bContinue = TRUE ; ULONG ulDosDevices = MAX_DOS_DEVICES ; do { // // let's finish loop // bContinue = FALSE ; CSmartBuffer pQueryBuffer ( ( ulDosDevices * sizeof ( TCHAR ) ) ); DWORD t_QueryStatus = QueryDosDevice ( NULL , (LPTSTR)((LPBYTE)pQueryBuffer) , ulDosDevices ) ; if ( t_QueryStatus ) { a_DosDeviceNameList = new TCHAR [ t_QueryStatus ] ; if (a_DosDeviceNameList == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } memcpy ( a_DosDeviceNameList , (void*)((LPBYTE)pQueryBuffer) , t_QueryStatus * sizeof ( TCHAR ) ) ; t_Status = TRUE; } else { if ( STATUS_BUFFER_TOO_SMALL == (NTSTATUS)NtCurrentTeb()->LastStatusValue ) { // // let's continue if the reason of failure // is just small buffer here // ulDosDevices = ulDosDevices * 2 ; bContinue = TRUE ; } } } while ( bContinue ) ; return t_Status ; } /***************************************************************************** * * FUNCTION : FindDosDeviceName * * DESCRIPTION : Finds the dos device symbolic link given an NT device name * * INPUTS : none * * OUTPUTS : nichts * * RETURNS : nada * * COMMENTS : * *****************************************************************************/ #define MAX_MAPPED_DEVICES 26 #define MAX_DEVICENAME_LENGTH 256 BOOL WINAPI FindDosDeviceName ( const TCHAR *a_DosDeviceNameList , const CHString a_SymbolicName , CHString &a_DosDevice , BOOL a_MappedDevice ) { BOOL t_Status = FALSE ; CSmartBuffer t_MappedDevices ; if ( a_MappedDevice ) { DWORD t_Length = GetLogicalDriveStrings ( 0 , NULL ) ; if (t_Length) { LPBYTE t_buff = new BYTE[(t_Length + 1) * sizeof(TCHAR)]; if (t_buff == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } t_MappedDevices = t_buff; if (!GetLogicalDriveStrings ( t_Length , (LPTSTR)((LPBYTE)t_MappedDevices) ) ) { DWORD t_Error = GetLastError () ; return FALSE; } } else { DWORD t_Error = GetLastError () ; return FALSE; } } const TCHAR *t_Device = a_DosDeviceNameList ; while ( *t_Device != NULL ) { CSmartBuffer pQueryBuffer ((MAX_DOS_DEVICES * sizeof (TCHAR))); DWORD t_QueryStatus = QueryDosDevice ( t_Device , (LPTSTR)((LPBYTE)pQueryBuffer) , MAX_DOS_DEVICES ) ; if ( t_QueryStatus ) { TCHAR *t_Symbolic = (LPTSTR)((LPBYTE)pQueryBuffer) ; while ( *t_Symbolic != NULL ) { if ( _wcsicmp ( a_SymbolicName , TOBSTRT(t_Symbolic) ) == 0 ) { /* * Atleast get a match even if there is no mapped drive */ t_Status = TRUE ; a_DosDevice = t_Device ; if ( a_MappedDevice ) { const TCHAR *t_CurrentDevice = (const LPTSTR)((LPBYTE)t_MappedDevices) ; while ( *t_CurrentDevice != NULL ) { if ( _tcsnicmp ( t_Device, t_CurrentDevice , 2 ) == 0 ) { t_Status = TRUE ; a_DosDevice = t_Device ; return TRUE ; } t_CurrentDevice = t_CurrentDevice + _tcslen ( t_CurrentDevice ) + 1 ; } } else { return TRUE ; } } t_Symbolic = t_Symbolic + _tcslen ( t_Symbolic ) + 1 ; } } else { DWORD t_Error = GetLastError () ; } t_Device = t_Device + _tcslen ( t_Device ) + 1 ; } return t_Status ; } BOOL CConfigMgrDevice::IsClass(LPCWSTR pwszClassName) { BOOL bRet = FALSE; CHString sTemp; if (GetClass(sTemp)) { if (sTemp.CompareNoCase(pwszClassName) == 0) { bRet = TRUE; } else { bRet = FALSE; } } else { CHString sClass(pwszClassName); sClass.MakeUpper(); WCHAR cGuid[128]; GUID gFoo = CConfigManager::s_ClassMap[sClass]; StringFromGUID2(gFoo, cGuid, sizeof(cGuid)/sizeof(WCHAR)); if (GetClassGUID(sTemp) && (sTemp.CompareNoCase(cGuid) == 0)) { bRet = TRUE; } } return bRet; } BOOL CConfigMgrDevice::GetRegStringProperty( LPCWSTR szProperty, CHString &strValue) { CHString strKeyName; DWORD dwRet; CRegistry reg; if (GetRegistryKeyName(strKeyName) && (dwRet = reg.Open(HKEY_LOCAL_MACHINE, strKeyName, KEY_QUERY_VALUE) == ERROR_SUCCESS)) { dwRet = reg.GetCurrentKeyValue(szProperty, strValue); } return dwRet == ERROR_SUCCESS; }