Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3464 lines
92 KiB

/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997-2002 Microsoft Corporation, All Rights Reserved
//
/////////////////////////////////////////////////////////////////////////
#include "precomp.h"
#include <assertbreak.h>
#include "poormansresource.h"
#include "resourcedesc.h"
#include "irqdesc.h"
#include <regstr.h>
#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 <cregcls.h>
#include "nt4svctoresmap.h"
#include "chwres.h"
#include "configmgrapi.h"
#include <map>
// 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;
}