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.
 
 
 
 
 
 

900 lines
30 KiB

//=================================================================
//
// Confgmgr.cpp
//
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//
// History:
// 10/17/97 jennymc Created
//
/////////////////////////////////////////////////////////////////////////
#define INITGUID
#include "precomp.h"
#include <cregcls.h>
#include <assertbreak.h>
#include "refptr.h"
#include "poormansresource.h"
#include "resourcedesc.h"
#include "cfgmgrdevice.h"
#include "irqdesc.h"
#include "DllUtils.h"
#include "dmadesc.h"
#include <brodcast.h>
#include <lockwrap.h>
#include "strings.h"
#include <smartptr.h>
#include <devguid.h>
static CCritSec map;
STRING2GUID CConfigManager::s_ClassMap;
BOOL CConfigManager::s_ClassIsValid = FALSE;
CConfigManager::CConfigManager( DWORD dwTypeToGet )
{
m_dwTypeToGet = dwTypeToGet;
if (!s_ClassIsValid)
{
CLockWrapper t_lockMap( map ) ;
// Check again now that we have the lock
if (!s_ClassIsValid)
{
s_ClassMap[_T("1394")] = GUID_DEVCLASS_1394;
s_ClassMap[_T("ADAPTER")] = GUID_DEVCLASS_ADAPTER;
s_ClassMap[_T("APMSUPPORT")] = GUID_DEVCLASS_APMSUPPORT;
s_ClassMap[_T("BATTERY")] = GUID_DEVCLASS_BATTERY;
s_ClassMap[_T("CDROM")] = GUID_DEVCLASS_CDROM;
s_ClassMap[_T("COMPUTER")] = GUID_DEVCLASS_COMPUTER;
s_ClassMap[_T("DECODER")] = GUID_DEVCLASS_DECODER;
s_ClassMap[_T("DISKDRIVE")] = GUID_DEVCLASS_DISKDRIVE;
s_ClassMap[_T("DISPLAY")] = GUID_DEVCLASS_DISPLAY;
s_ClassMap[_T("FDC")] = GUID_DEVCLASS_FDC;
s_ClassMap[_T("FLOPPYDISK")] = GUID_DEVCLASS_FLOPPYDISK;
s_ClassMap[_T("GPS")] = GUID_DEVCLASS_GPS;
s_ClassMap[_T("HDC")] = GUID_DEVCLASS_HDC;
s_ClassMap[_T("HIDCLASS")] = GUID_DEVCLASS_HIDCLASS;
s_ClassMap[_T("IMAGE")] = GUID_DEVCLASS_IMAGE;
s_ClassMap[_T("INFRARED")] = GUID_DEVCLASS_INFRARED;
s_ClassMap[_T("KEYBOARD")] = GUID_DEVCLASS_KEYBOARD;
s_ClassMap[_T("LEGACYDRIVER")] = GUID_DEVCLASS_LEGACYDRIVER;
s_ClassMap[_T("MEDIA")] = GUID_DEVCLASS_MEDIA;
s_ClassMap[_T("MODEM")] = GUID_DEVCLASS_MODEM;
s_ClassMap[_T("MONITOR")] = GUID_DEVCLASS_MONITOR;
s_ClassMap[_T("MOUSE")] = GUID_DEVCLASS_MOUSE;
s_ClassMap[_T("MTD")] = GUID_DEVCLASS_MTD;
s_ClassMap[_T("MULTIFUNCTION")] = GUID_DEVCLASS_MULTIFUNCTION;
s_ClassMap[_T("MULTIPORTSERIAL")] = GUID_DEVCLASS_MULTIPORTSERIAL;
s_ClassMap[_T("NET")] = GUID_DEVCLASS_NET;
s_ClassMap[_T("NETCLIENT")] = GUID_DEVCLASS_NETCLIENT;
s_ClassMap[_T("NETSERVICE")] = GUID_DEVCLASS_NETSERVICE;
s_ClassMap[_T("NETTRANS")] = GUID_DEVCLASS_NETTRANS;
s_ClassMap[_T("NODRIVER")] = GUID_DEVCLASS_NODRIVER;
s_ClassMap[_T("PCMCIA")] = GUID_DEVCLASS_PCMCIA;
s_ClassMap[_T("PORTS")] = GUID_DEVCLASS_PORTS;
s_ClassMap[_T("PRINTER")] = GUID_DEVCLASS_PRINTER;
s_ClassMap[_T("PRINTERUPGRADE")] = GUID_DEVCLASS_PRINTERUPGRADE;
s_ClassMap[_T("SCSIADAPTER")] = GUID_DEVCLASS_SCSIADAPTER;
s_ClassMap[_T("SMARTCARDREADER")] = GUID_DEVCLASS_SMARTCARDREADER;
s_ClassMap[_T("SOUND")] = GUID_DEVCLASS_SOUND;
s_ClassMap[_T("SYSTEM")] = GUID_DEVCLASS_SYSTEM;
s_ClassMap[_T("TAPEDRIVE")] = GUID_DEVCLASS_TAPEDRIVE;
s_ClassMap[_T("UNKNOWN")] = GUID_DEVCLASS_UNKNOWN;
s_ClassMap[_T("USB")] = GUID_DEVCLASS_USB;
s_ClassMap[_T("VOLUME")] = GUID_DEVCLASS_VOLUME;
s_ClassIsValid = TRUE;
}
}
}
////////////////////////////////////////////////////////////////////////
//
// Reads the config manager registry keys for win98 and win95
//
////////////////////////////////////////////////////////////////////////
BOOL CConfigManager::BuildListsForThisDevice(CConfigMgrDevice *pDevice)
{
CResourceCollection resourceList;
CHString sDeviceName, sClass, sKey(_T("Enum\\"));
BOOL fRc = FALSE;
CRegistry RegInfo;
// Extract the device name
sDeviceName = pDevice->GetDeviceDesc();
// Pull the resource list out and enumerate it.
pDevice->GetResourceList( resourceList );
sKey += pDevice->GetHardwareKey();
if (RegInfo.Open(HKEY_LOCAL_MACHINE, sKey, KEY_READ) == ERROR_SUCCESS) {
RegInfo.GetCurrentKeyValue(L"Class", sClass);
}
REFPTR_POSITION pos;
if ( resourceList.BeginEnum( pos ) ){
PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor = NULL;// Watch the scoping on this guy!
DWORD dwCount = 0;
#if NTONLY >= 5
// Go find the resource descriptor for this device
CHString sRegKeyName;
CRegistry Reg;
CSmartBuffer Buffer; // Watch the scoping on this guy!
if ( (Reg.Open(HKEY_LOCAL_MACHINE, L"hardware\\resourcemap\\PnP Manager\\PNPManager", KEY_QUERY_VALUE) == ERROR_SUCCESS) &&
pDevice->GetPhysicalDeviceObjectName(sRegKeyName) )
{
sRegKeyName += L".raw";
DWORD dwValueType;
DWORD dwValueDataSize = Reg.GetLongestValueData() + 2 ;
Buffer = new BYTE[dwValueDataSize];
if ((LPBYTE)Buffer == NULL)
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
if(RegQueryValueEx(Reg.GethKey(), sRegKeyName, NULL,
&dwValueType, (LPBYTE)Buffer, &dwValueDataSize) == ERROR_SUCCESS)
{
if(dwValueType == REG_FULL_RESOURCE_DESCRIPTOR)
{
dwCount = 1 ;
pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) (LPBYTE)Buffer ;// Watch the scoping on this guy!
}
else if(dwValueType == REG_RESOURCE_LIST)
{
dwCount = ((PCM_RESOURCE_LIST) (LPBYTE)Buffer)->Count ;
pFullDescriptor = ((PCM_RESOURCE_LIST) (LPBYTE)Buffer)->List ;// Watch the scoping on this guy!
}
}
}
#endif
CHString sResource;
//=========================================================
// For each descriptor we find, if it's not ignored,
// we should get the string data, and place it in the
// appropriate list based on Type.
//=========================================================
CResourceDescriptorPtr pResDesc;
for( pResDesc.Attach(resourceList.GetNext( pos ));
NULL != pResDesc;
pResDesc.Attach(resourceList.GetNext( pos )) )
{
DWORD t_dwResType = pResDesc->GetResourceType();
if ( (!pResDesc->IsIgnored()) &&
((m_dwTypeToGet == ResType_All) || (m_dwTypeToGet == t_dwResType) ) )
{
switch ( t_dwResType )
{
case ResType_DMA:
DMA_INFO *pDMA_Info;
DMA_DES *pTmp;
pDMA_Info = new DMA_INFO;
if (pDMA_Info != NULL)
{
try
{
DWORD dwChannelWidth;
pTmp = (DMA_DES*) pResDesc->GetResource();
dwChannelWidth = (pTmp->DD_Flags) & 0x0003;
pDMA_Info->ChannelWidth = 0;
if( dwChannelWidth == 0 )
{
pDMA_Info->ChannelWidth = 8;
}
else if( dwChannelWidth == 1 )
{
pDMA_Info->ChannelWidth = 16;
}
else if( dwChannelWidth == 2 )
{
pDMA_Info->ChannelWidth = 32;
}
pDMA_Info->DeviceType = sClass;
pDMA_Info->Channel = pTmp->DD_Alloc_Chan;
pResDesc->GetOwnerDeviceID(pDMA_Info->OwnerDeviceId);
pResDesc->GetOwnerName(pDMA_Info->OwnerName);
pDMA_Info->OEMNumber = pResDesc->GetOEMNumber();
pDMA_Info->Port = GetDMAPort(pFullDescriptor, dwCount, pTmp->DD_Alloc_Chan);
}
catch ( ... )
{
delete pDMA_Info;
throw ;
}
// real DMA channels are in the range 0-7
// sometimes the confug mugger reports channels
// with great big numbers - we don't care
if (pDMA_Info->Channel < 8)
{
try
{
m_List.Add(pDMA_Info);
}
catch ( ... )
{
delete pDMA_Info;
throw ;
}
}
else
{
delete pDMA_Info;
}
}
else
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
break;
case ResType_IRQ:
IRQ_INFO *pIRQ_Info;
IRQ_DES *pTmpIrq;
pIRQ_Info = new IRQ_INFO;
if (pIRQ_Info != NULL)
{
try
{
pTmpIrq = (IRQ_DES*) pResDesc->GetResource();
pIRQ_Info->Shareable = pTmpIrq->IRQD_Flags;
pIRQ_Info->IRQNumber = pTmpIrq->IRQD_Alloc_Num; // Allocated IRQ number
pIRQ_Info->DeviceType = sClass;
pResDesc->GetOwnerDeviceID(pIRQ_Info->OwnerDeviceId);
pResDesc->GetOwnerName(pIRQ_Info->OwnerName);
pIRQ_Info->OEMNumber = pResDesc->GetOEMNumber();
pIRQ_Info->Vector = GetIRQVector(pFullDescriptor, dwCount, pTmpIrq->IRQD_Alloc_Num);
m_List.Add(pIRQ_Info);
}
catch ( ... )
{
delete pIRQ_Info;
throw ;
}
}
else
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
break;
case ResType_IO:
IO_INFO *pIO_Info;
IOWBEM_DES *pTmpIO;
pIO_Info = new IO_INFO;
if (pIO_Info != NULL)
{
try
{
pTmpIO = (IOWBEM_DES*) pResDesc->GetResource();
pIO_Info->DeviceType = sClass;
pIO_Info->StartingAddress = pTmpIO->IOD_Alloc_Base;
pIO_Info->EndingAddress = pTmpIO->IOD_Alloc_End;
pIO_Info->Alias = pTmpIO->IOD_Alloc_Alias;
pIO_Info->Decode = pTmpIO->IOD_Alloc_Decode;
pResDesc->GetOwnerName(pIO_Info->OwnerName);
m_List.Add(pIO_Info);
}
catch ( ... )
{
delete pIO_Info;
throw ;
}
}
else
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
break;
case ResType_Mem:
MEM_INFO *pMem_Info;
MEM_DES *pTmpMem;
pMem_Info = new MEM_INFO;
if (pMem_Info != NULL)
{
try
{
pTmpMem = (MEM_DES*) pResDesc->GetResource();
pMem_Info->DeviceType = sClass;
pMem_Info->StartingAddress = pTmpMem->MD_Alloc_Base;
pMem_Info->EndingAddress = pTmpMem->MD_Alloc_End;
pResDesc->GetOwnerName(pMem_Info->OwnerName);
pMem_Info->MemoryType = GetMemoryType(pFullDescriptor, dwCount, pTmpMem->MD_Alloc_Base);
m_List.Add(pMem_Info);
}
catch ( ... )
{
delete pMem_Info;
throw ;
}
}
else
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
break;
} // SWITCH
} // IF !IsIgnored
} // For EnumResources
resourceList.EndEnum();
} // IF BeginEnum()
return fRc;
}
////////////////////////////////////////////////////////////////////////
void CConfigManager::ResetList()
{
IO_INFO *pIOInfo;
IRQ_INFO *pIRQInfo;
DMA_INFO *pDMAInfo;
MEM_INFO *pMemInfo;
int nNum = m_List.GetSize();
for( int i=0; i < nNum; i++ ){
switch (m_dwTypeToGet) {
case ResType_DMA:
pDMAInfo = ( DMA_INFO *) m_List.GetAt(i);
delete pDMAInfo;
break;
case ResType_IRQ:
pIRQInfo = ( IRQ_INFO *) m_List.GetAt(i);
delete pIRQInfo;
break;
case ResType_IO:
pIOInfo = ( IO_INFO *) m_List.GetAt(i);
delete pIOInfo;
break;
case ResType_Mem:
pMemInfo = ( MEM_INFO *) m_List.GetAt(i);
delete pMemInfo;
break;
default:
ASSERT_BREAK(0);
break;
}
}
m_List.RemoveAll();
}
////////////////////////////////////////////////////////////////////////
BOOL CConfigManager::RefreshList()
{
BOOL bRc = FALSE;
//===========================================================
// Reset lists
//===========================================================
ResetList();
// Get all the available devices and check each of them for resources used
CDeviceCollection deviceList;
if ( GetDeviceList( deviceList ) )
{
REFPTR_POSITION pos;
if ( deviceList.BeginEnum( pos ) )
{
CConfigMgrDevicePtr pDevice;
for ( pDevice.Attach(deviceList.GetNext( pos )) ;
pDevice != NULL;
pDevice.Attach(deviceList.GetNext( pos )))
{
BuildListsForThisDevice(pDevice);
}
// For every begin, there is an End
deviceList.EndEnum();
} // BeginEnum
bRc = TRUE;
}
return bRc;
/*
//===========================================================
// Enumerate all
//===========================================================
CRegistry Reg;
CHString sDevice;
if( ERROR_SUCCESS == Reg.OpenAndEnumerateSubKeys(HKEY_DYN_DATA, "Config Manager\\Enum", KEY_READ )){
while( ERROR_SUCCESS == Reg.GetCurrentSubKeyName(sDevice) ){
//===========================================================
// Since we're keeping back pointers to the Device Object,
// new him, rather than keeping him on the stack so we're
// not dependent on the order of destruction as to how
// safe we are.
//===========================================================
CConfigMgrDevice *pDevice = new CConfigMgrDevice(sDevice,m_dwTypeToGet);
if ( NULL != pDevice ){
if( !BuildListsForThisDevice(pDevice) ){
// We're done with this pointer
delete pDevice;
}
// otherwise ptr is deleted after device is added to list
} // IF NULL != pDevice
bRc = TRUE;
if( Reg.NextSubKey() != ERROR_SUCCESS ){
break;
}
}
}
return bRc;
*/
}
// valid properties for filtering
//#define CM_DRP_DEVICEDESC (0x00000001) // DeviceDesc REG_SZ property (RW)
//#define CM_DRP_SERVICE (0x00000005) // Service REG_SZ property (RW)
//#define CM_DRP_CLASS (0x00000008) // Class REG_SZ property (RW)
//#define CM_DRP_CLASSGUID (0x00000009) // ClassGUID REG_SZ property (RW)
//#define CM_DRP_DRIVER (0x0000000A) // Driver REG_SZ property (RW)
//#define CM_DRP_MFG (0x0000000C) // Mfg REG_SZ property (RW)
//#define CM_DRP_FRIENDLYNAME (0x0000000D) // FriendlyName REG_SZ property (RW)
//#define CM_DRP_LOCATION_INFORMATION (0x0000000E) // LocationInformation REG_SZ property (RW)
//#define CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME (0x0000000F) // PhysicalDeviceObjectName REG_SZ property (R)
//#define CM_DRP_MIN (0x00000001)
//#define CM_DRP_MAX (0x00000017)
BOOL CConfigManager::GetDeviceList( CDeviceCollection& deviceList, LPCWSTR pszFilter/*=NULL*/, ULONG ulProperty/*=CM_DRP_MAX*/ )
{
CONFIGRET cr = CR_INVALID_POINTER;
// Dump the list first
deviceList.Empty();
DEVNODE dnRoot;
CConfigMgrAPI* t_pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ;
try
{
if ( t_pconfigmgr )
{
if ( t_pconfigmgr->IsValid () )
{
if ( CR_SUCCESS == ( cr = t_pconfigmgr->CM_Locate_DevNode( &dnRoot, NULL, 0 ) ) )
{
DEVNODE dnFirst;
if ( CR_SUCCESS == ( cr = t_pconfigmgr->CM_Get_Child( &dnFirst, dnRoot, 0 ) ) )
{
// This should only fail in case we are unable to allocate a device
if ( !WalkDeviceTree( dnFirst, deviceList, pszFilter, ulProperty, t_pconfigmgr ) )
{
cr = CR_OUT_OF_MEMORY;
}
}
}
CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, t_pconfigmgr ) ;
t_pconfigmgr = NULL ;
}
else
{
::SetLastError ( t_pconfigmgr->GetCreationError () );
}
}
}
catch ( ... )
{
if ( t_pconfigmgr )
{
CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, t_pconfigmgr ) ;
t_pconfigmgr = NULL ;
}
throw ;
}
return ( CR_SUCCESS == cr );
}
// This device MUST be Released!
BOOL CConfigManager::LocateDevice( LPCWSTR pszDeviceID, CConfigMgrDevicePtr & pCfgMgrDevice )
{
CONFIGRET cr = CR_INVALID_POINTER;
if ( (pszDeviceID != NULL) && (pszDeviceID[0] != L'\0') )
{
CConfigMgrAPI* t_pconfigmgr = ( CConfigMgrAPI *) CResourceManager::sm_TheResourceManager.GetResource ( guidCFGMGRAPI, NULL ) ;
try
{
if ( t_pconfigmgr )
{
if ( t_pconfigmgr->IsValid () )
{
DEVNODE dnRoot;
if ( CR_SUCCESS == ( cr = t_pconfigmgr->CM_Locate_DevNode( &dnRoot, bstr_t(pszDeviceID), 0 ) ) )
{
pCfgMgrDevice.Attach(new CConfigMgrDevice( dnRoot, m_dwTypeToGet ));
}
CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, t_pconfigmgr ) ;
t_pconfigmgr = NULL ;
}
else
{
::SetLastError ( t_pconfigmgr->GetCreationError () );
}
}
}
catch ( ... )
{
if ( t_pconfigmgr )
{
CResourceManager::sm_TheResourceManager.ReleaseResource ( guidCFGMGRAPI, t_pconfigmgr ) ;
t_pconfigmgr = NULL ;
}
throw ;
}
}
return ( CR_SUCCESS == cr );
}
BOOL CConfigManager::WalkDeviceTree( DEVNODE dn, CDeviceCollection& deviceList, LPCWSTR pszFilter, ULONG ulFilterProperty, CConfigMgrAPI *a_pconfigmgr )
{
BOOL fReturn = TRUE;
// While it would make more sense to check the filter in WalkDeviceTree2,
// we can't. Config manager sometimes has a loop in its nodes. As a result,
// we need to be checking the entire list for a loop, so we need to apply
// the filter here.
if ( NULL == pszFilter)
{
// Load ALL the nodes
fReturn = WalkDeviceTree2(dn, deviceList, a_pconfigmgr );
}
else
{
CDeviceCollection deviceList2;
CConfigMgrDevicePtr pDevice;
fReturn = WalkDeviceTree2(dn, deviceList2, a_pconfigmgr );
if (fReturn)
{
// Walk all the nodes looking for ones that match the filter. Copy the matches
// to the passed in array.
CHString strFilterValue;
DWORD dwSize = deviceList2.GetSize();
for (int x=0; x < dwSize; x++)
{
pDevice.Attach(deviceList2.GetAt(x));
// Apply our filter, and save the device pointer to the list only
// if the device property value is the same as the filter.
if ( pDevice->GetStringProperty( ulFilterProperty, strFilterValue ) )
{
if ( strFilterValue.CompareNoCase( pszFilter ) == 0 )
{
fReturn = deviceList.Add( pDevice );
}
}
}
}
}
return fReturn;
}
BOOL CConfigManager::WalkDeviceTree2( DEVNODE dn, CDeviceCollection& deviceList, CConfigMgrAPI *a_pconfigmgr )
{
BOOL fReturn = TRUE; // Assume TRUE, the only failure is where we
// beef allocating a device.
BOOL fIsLoop = FALSE; // Config manager has a bug that causes a loop in device lists<sigh>
CConfigMgrDevicePtr pDevice;
// CHString strFilterValue;
DEVNODE dnSibling,
dnChild;
// We're walking the list for siblings and children. Waliing for siblings
// is done in the context of the following loop, since siblings are at
// the same level in the tree. Walking for children is, of course, recursive.
do
{
// Store siblings, since we will proceed from it to the next
// sibling.
if ( CR_SUCCESS != a_pconfigmgr->CM_Get_Sibling( &dnSibling, dn, 0 ) )
{
dnSibling = NULL;
}
// Allocate a new device, and if it passes through our filter, or if
// there is no filter, go ahead and store the device in the device collection.
pDevice.Attach(new CConfigMgrDevice( dn, m_dwTypeToGet ));
if ( NULL != pDevice )
{
if (deviceList.GetSize() > CFGMGR_WORRY_SIZE)
{
fIsLoop = CheckForLoop(deviceList, pDevice);
}
if (!fIsLoop)
{
// While it would make more sense to check the filter in WalkDeviceTree2,
// we can't. Config manager sometimes has a loop in its nodes. As a result,
// we need to be checking the entire list for a loop, so we need to apply
// the filter here.
fReturn = deviceList.Add( pDevice );
}
} // IF NULL != pszDevice
else
{
// We just beefed on memory, so bail out while the gettin's good
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
// If we have a child, we must walk recursively.
// Note that fReturn of FALSE supercedes all of this.
if ( fReturn && !fIsLoop && CR_SUCCESS == a_pconfigmgr->CM_Get_Child( &dnChild, dn, 0 ) )
{
fReturn = WalkDeviceTree2( dnChild, deviceList, a_pconfigmgr );
}
// The new active node will be our sibling.
dn = dnSibling;
} while ( fReturn && NULL != dn && !fIsLoop );
return fReturn;
}
// Check to see if pInDevice already exists in deviceList
BOOL CConfigManager::CheckForLoop(CDeviceCollection& deviceList, CConfigMgrDevice *pInDevice)
{
DWORD dwSize, x, y;
BOOL bIsLoop = FALSE;
CConfigMgrDevicePtr pDevice1;
CConfigMgrDevicePtr pDevice2;
// Get the list size
dwSize = deviceList.GetSize()-1;
// If it is in here, it is probably close to the end, let's walk backward
for (x = dwSize; ((x > 0) && (!bIsLoop)); x--)
{
pDevice1.Attach(deviceList.GetAt(x));
// This compares the device nodes (see CConfigMgrDevice)
if (*pDevice1 == *pInDevice)
{
// Yup, there's a loop
bIsLoop = TRUE;
}
}
// If there is a loop, let's drop off the duplicated elements
if (bIsLoop)
{
// Remember, x get decremented one more time from the last loop
y = dwSize;
do {
pDevice1.Attach(deviceList.GetAt(x--));
pDevice2.Attach(deviceList.GetAt(y--));
} while ((*pDevice1 == *pDevice2) && (x > 0));
// Delete all the duplicate elements
y++;
for (x = dwSize; x > y; x--)
{
deviceList.Remove(x);
}
}
return bIsLoop;
}
BOOL CConfigManager::GetDeviceListFilterByClass( CDeviceCollection& deviceList, LPCWSTR pszFilter )
{
#ifdef NTONLY
if (IsWinNT5())
{
CHString sClassName(pszFilter);
sClassName.MakeUpper();
WCHAR cGuid[128];
StringFromGUID2(s_ClassMap[sClassName], cGuid, sizeof(cGuid)/sizeof(WCHAR));
return GetDeviceList( deviceList, cGuid, CM_DRP_CLASSGUID );
}
else
{
return GetDeviceList( deviceList, pszFilter, CM_DRP_CLASS );
}
#else
return GetDeviceList( deviceList, pszFilter, CM_DRP_CLASS );
#endif
}
// Given a FULL_RESOURCE_DESCRIPTOR, find the specified IRQ number, and return its vector
DWORD CConfigManager::GetIRQVector(PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor, DWORD dwFullCount, DWORD dwIRQNum)
{
if (NULL != pFullDescriptor)
{
PCM_PARTIAL_RESOURCE_LIST pPartialList ;
for (DWORD x=0; x < dwFullCount; x++)
{
pPartialList = &pFullDescriptor->PartialResourceList ;
for (DWORD y = 0; y < pPartialList->Count; y++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor = &pPartialList->PartialDescriptors[y];
if ( (CmResourceTypeInterrupt == pDescriptor->Type) &&
( pDescriptor->u.Interrupt.Level == dwIRQNum)
)
{
return pDescriptor->u.Interrupt.Vector;
}
}
pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) &pPartialList->PartialDescriptors[pPartialList->Count] ;
}
ASSERT_BREAK(0);
}
return 0xffffffff;
}
// Given a FULL_RESOURCE_DESCRIPTOR, find the specified DMA channel, and return its port
DWORD CConfigManager::GetDMAPort(PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor, DWORD dwFullCount, DWORD dwChannel)
{
if (NULL != pFullDescriptor)
{
PCM_PARTIAL_RESOURCE_LIST pPartialList ;
for (DWORD x=0; x < dwFullCount; x++)
{
pPartialList = &pFullDescriptor->PartialResourceList ;
for (DWORD y = 0; y < pPartialList->Count; y++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor = &pPartialList->PartialDescriptors[y];
if ( (CmResourceTypeDma == pDescriptor->Type) &&
( pDescriptor->u.Dma.Channel == dwChannel)
)
{
return pDescriptor->u.Dma.Port;
}
}
pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) &pPartialList->PartialDescriptors[pPartialList->Count] ;
}
ASSERT_BREAK(0);
}
return 0xffffffff;
}
// Given a FULL_RESOURCE_DESCRIPTOR, find the specified startingaddress, and return its MemoryType
LPCWSTR CConfigManager::GetMemoryType(PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor, DWORD dwCount, ULONGLONG ulStartAddress)
{
if (NULL != pFullDescriptor)
{
PCM_PARTIAL_RESOURCE_LIST pPartialList ;
for (DWORD x=0; x < dwCount; x++)
{
pPartialList = &pFullDescriptor->PartialResourceList ;
for (DWORD y = 0; y < pPartialList->Count; y++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor = &pPartialList->PartialDescriptors[y];
LARGE_INTEGER liTemp; // Used to avoid 64bit alignment problems
liTemp.HighPart = pDescriptor->u.Memory.Start.HighPart;
liTemp.LowPart = pDescriptor->u.Memory.Start.LowPart;
if ( (CmResourceTypeMemory == pDescriptor->Type) &&
( liTemp.QuadPart == ulStartAddress)
)
{
switch(pDescriptor->Flags)
{
case CM_RESOURCE_MEMORY_READ_WRITE :
{
return IDS_MTReadWrite;
}
case CM_RESOURCE_MEMORY_READ_ONLY:
{
return IDS_MTReadOnly;
}
case CM_RESOURCE_MEMORY_WRITE_ONLY:
{
return IDS_MTWriteOnly;
}
case CM_RESOURCE_MEMORY_PREFETCHABLE:
{
return IDS_MTPrefetchable;
}
}
return L"";
}
}
pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) &pPartialList->PartialDescriptors[pPartialList->Count] ;
}
ASSERT_BREAK(0);
}
return L"";
}