|
|
//====================================================================
//
// chwres.cpp -- Hardware resource access wrapper class implementation
//
// Copyright (c) 1996-2001 Microsoft Corporation, All Rights Reserved
//
// Revisions: 02/25/97 a-jmoon Adapted from original horrible
// code -- only comments remain.
//
//====================================================================
#include "precomp.h"
#include <cregcls.h>
#include "chwres.h"
/*****************************************************************************
* * FUNCTION : CHWResource::CHWResource * * DESCRIPTION : Constructor * * INPUTS : none * * OUTPUTS : none * * RETURNS : nothing * * COMMENTS : Initialization * *****************************************************************************/
#ifdef NTONLY
CHWResource::CHWResource() { // Zero out public structure
//==========================
memset(&_SystemResourceList, 0, sizeof(_SystemResourceList)) ; }
/*****************************************************************************
* * FUNCTION : CHWResource::~CHWResource * * DESCRIPTION : Destructor * * INPUTS : none * * OUTPUTS : none * * RETURNS : nothing * * COMMENTS : Cleanup * *****************************************************************************/
CHWResource::~CHWResource() { // Make sure we've destroyed everything
//=====================================
DestroySystemResourceLists() ; }
/*****************************************************************************
* * FUNCTION : CHWResource::DestroySystemResourceLists * * DESCRIPTION : Walks list of devices & frees associated resource records * * INPUTS : none * * OUTPUTS : none * * RETURNS : nothing * * COMMENTS : * *****************************************************************************/
void CHWResource::DestroySystemResourceLists() { LPDEVICE pDevice ; LPRESOURCE_DESCRIPTOR pResource ;
while(_SystemResourceList.DeviceHead != NULL) { pDevice = _SystemResourceList.DeviceHead ; _SystemResourceList.DeviceHead = pDevice->Next ;
delete pDevice->Name ; delete pDevice->KeyName ;
while(pDevice->ResourceDescriptorHead != NULL) { pResource = pDevice->ResourceDescriptorHead ; pDevice->ResourceDescriptorHead = pResource->NextDiff ;
delete pResource ; }
delete pDevice ; }
memset(&_SystemResourceList, 0, sizeof(_SystemResourceList)) ; }
/*****************************************************************************
* * FUNCTION : CHWResource::CreateSystemResourceLists * CHWResource::EnumerateResources * CHWResource::CreateResourceList * CHWResource::CreateResourceRecord * * DESCRIPTION : These four routines recursively enumerate device records * under HKEY_LOCAL_MACHINE\Hardware\ResourceMap and its * subkeys, creating a linked list of discovered devices. * Under each device, a linked list of resources owned by * the device is also created. Resource records are also * linked into chains specific to the type of resource. * * INPUTS : none * * OUTPUTS : none * * RETURNS : nothing * * COMMENTS : Initialization * *****************************************************************************/
void CHWResource::CreateSystemResourceLists() { // Start w/clean slate
//====================
DestroySystemResourceLists() ;
// Begin device enumeration at HKLM\Hardware\ResourceMap
//======================================================
EnumerateResources(_T("Hardware\\ResourceMap")) ; }
void CHWResource::EnumerateResources(CHString sKeyName) { CRegistry Reg ; CHString sSubKeyName, sDeviceName ; int iFirst ; DWORD i, dwCount, dwValueType, dwValueNameSize, dwValueDataSize ; TCHAR *pValueName ; unsigned char *pValueData ; PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor ;
// Open target key
//================
if(Reg.Open(HKEY_LOCAL_MACHINE, (LPCTSTR) sKeyName, KEY_READ) != ERROR_SUCCESS) { return ; }
// First, enumerate subkeys
//=========================
for( ; ; ) { if(Reg.GetCurrentSubKeyName(sSubKeyName) == ERROR_SUCCESS) { EnumerateResources(sKeyName + "\\" + sSubKeyName) ; }
if(Reg.NextSubKey() != ERROR_SUCCESS) { break ; } }
// Extract this subkey's name
//===========================
iFirst = sKeyName.ReverseFind('\\') ; sSubKeyName = sKeyName.Mid(iFirst + 1, sKeyName.GetLength() - iFirst) ;
// Create name & data buffers
//===========================
pValueName = new TCHAR[Reg.GetLongestValueName() + 2] ; pValueData = new unsigned char[Reg.GetLongestValueData() + 2] ;
if(pValueName == NULL || pValueData == NULL) {
delete [] pValueName ; delete [] pValueData ;
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; }
// Enumerate subkeys
//==================
try { for(i = 0 ; i < Reg.GetValueCount() ; i++) {
// We need type data, so can't use the CRegistry wrapper
//======================================================
dwValueNameSize = Reg.GetLongestValueName() + 2 ; dwValueDataSize = Reg.GetLongestValueData() + 2 ;
if(RegEnumValue(Reg.GethKey(), i, pValueName, &dwValueNameSize, NULL, &dwValueType, pValueData, &dwValueDataSize) != ERROR_SUCCESS) { continue ; }
// Only deal w/'Raw' data
//=======================
sDeviceName = pValueName ; if(sDeviceName.Right(4) != _T(".Raw")) {
continue ; }
// We've found some resource records -- extract device name
//=========================================================
iFirst = sDeviceName.ReverseFind('\\') ; if(iFirst == -1) { // No device in value name -- device is subkey
//============================================
sDeviceName = sSubKeyName ; } else { sDeviceName = sDeviceName.Mid(iFirst + 1, sDeviceName.GetLength() - 5 - iFirst) ; }
if(sDeviceName.IsEmpty()) { continue ; }
// Based on returned type, set up for resource enumeration
//========================================================
if(dwValueType == REG_FULL_RESOURCE_DESCRIPTOR) { dwCount = 1 ; pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) pValueData ; } else if(dwValueType == REG_RESOURCE_LIST) { dwCount = ((PCM_RESOURCE_LIST) pValueData)->Count ; pFullDescriptor = ((PCM_RESOURCE_LIST) pValueData)->List ; } else { continue ; }
// Add the device & resources to system lists
//===========================================
CreateResourceList(sDeviceName, dwCount, pFullDescriptor, sKeyName) ; } } catch ( ... ) { delete [] pValueName ; delete [] pValueData ;
throw; }
delete [] pValueName ; delete [] pValueData ;
Reg.Close() ; }
void CHWResource::CreateResourceList(CHString sDeviceName, DWORD dwFullResourceCount, PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor, CHString sKeyName) { LPDEVICE pDevice ; DWORD i, j ; PCM_PARTIAL_RESOURCE_LIST pPartialList ;
// Locate/create record for device
//================================
pDevice = _SystemResourceList.DeviceHead ; while(pDevice != NULL) {
if(sDeviceName == pDevice->Name) {
break ; }
pDevice = pDevice->Next ; }
if(pDevice == NULL) {
// Device not found -- create new device record
//=============================================
pDevice = new DEVICE ; if(pDevice == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; }
memset(pDevice, 0, sizeof(DEVICE)) ;
pDevice->Name = new TCHAR[sDeviceName.GetLength() + 2] ; if(pDevice->Name == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; }
try { _tcscpy(pDevice->Name, LPCTSTR(sDeviceName)) ;
pDevice->KeyName = new TCHAR [sKeyName.GetLength() + 2] ; if(pDevice->KeyName == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; }
_tcscpy(pDevice->KeyName, LPCTSTR(sKeyName)) ;
if(_SystemResourceList.DeviceHead == NULL) { _SystemResourceList.DeviceHead = pDevice ; } else { _SystemResourceList.DeviceTail->Next = pDevice ; }
_SystemResourceList.DeviceTail = pDevice ; } catch ( ... ) { delete pDevice; throw ; } }
// Create record for each owned resource
//======================================
for(i = 0 ; i < dwFullResourceCount ; i++) { pPartialList = &pFullDescriptor->PartialResourceList ;
for(j = 0 ; j < pPartialList->Count; j++) { CreateResourceRecord(pDevice, pFullDescriptor->InterfaceType, pFullDescriptor->BusNumber, &pPartialList->PartialDescriptors[j]) ; }
// Point to next full descriptor
//==============================
pFullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) &pPartialList->PartialDescriptors[pPartialList->Count] ; } }
void CHWResource::CreateResourceRecord(LPDEVICE pDevice, INTERFACE_TYPE InterfaceType, ULONG Bus, PCM_PARTIAL_RESOURCE_DESCRIPTOR pResource) { LPRESOURCE_DESCRIPTOR pNewResource, *pHead, *pTail, pCurrent, pLast ;
// Only deal w/'known' resource types
//===================================
if(pResource->Type != CmResourceTypePort && pResource->Type != CmResourceTypeInterrupt && pResource->Type != CmResourceTypeMemory && pResource->Type != CmResourceTypeDma ) { return ; }
// Create new record for resource & add to device's list
//======================================================
pNewResource = new RESOURCE_DESCRIPTOR ; if(pNewResource == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; }
try { memset(pNewResource, 0, sizeof(RESOURCE_DESCRIPTOR)) ;
memcpy(&pNewResource->CmResourceDescriptor, pResource, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)) ;
pNewResource->Owner = pDevice ; pNewResource->Bus = Bus; pNewResource->InterfaceType = InterfaceType;
if(pDevice->ResourceDescriptorHead == NULL) {
pDevice->ResourceDescriptorHead = pNewResource ; } else {
pDevice->ResourceDescriptorTail->NextDiff = pNewResource ; }
pDevice->ResourceDescriptorTail = pNewResource ; } catch ( ... ) { delete pNewResource; throw ; }
// Locate insertion point into sorted type-specific list
//======================================================
switch(pResource->Type) { case CmResourceTypePort :
pHead = &_SystemResourceList.PortHead ; pTail = &_SystemResourceList.PortTail ;
pCurrent = *pHead ; pLast = NULL ;
LARGE_INTEGER liTemp; // Used to avoid 64bit alignment problems
liTemp.HighPart = pResource->u.Port.Start.HighPart; liTemp.LowPart = pResource->u.Port.Start.LowPart;
while(pCurrent != NULL) { LARGE_INTEGER liTemp2; // Used to avoid 64bit alignment problems
liTemp2.HighPart = pCurrent->CmResourceDescriptor.u.Port.Start.HighPart; liTemp2.LowPart = pCurrent->CmResourceDescriptor.u.Port.Start.LowPart;
if (liTemp2.QuadPart < liTemp.QuadPart) { pLast = pCurrent ; pCurrent = pCurrent->NextSame ; } else { break; } }
break;
case CmResourceTypeInterrupt : { pHead = &_SystemResourceList.InterruptHead ; pTail = &_SystemResourceList.InterruptTail ;
pCurrent = *pHead ; pLast = NULL ;
ULONGLONG iIRQ = pResource->u.Interrupt.Level;
// If the IRQ to add is less than the current IRQ, OR
// if the IRQ to add is the same as the current IRQ and the current
// IRQ is not an internal one, put it after the current one. This
// will make sure that internal IRQs are listed last in the list.
while (pCurrent != NULL && ( (pCurrent->CmResourceDescriptor.u.Interrupt.Level < iIRQ) || ((pCurrent->CmResourceDescriptor.u.Interrupt.Level == iIRQ) && (pCurrent->InterfaceType != Internal)) )) { pLast = pCurrent ; pCurrent = pCurrent->NextSame ; }
break; }
case CmResourceTypeMemory : {
pHead = &_SystemResourceList.MemoryHead ; pTail = &_SystemResourceList.MemoryTail ;
pCurrent = *pHead ; pLast = NULL ;
LARGE_INTEGER liTemp; // Used to avoid 64bit alignment problems
liTemp.HighPart = pResource->u.Memory.Start.HighPart; liTemp.LowPart = pResource->u.Memory.Start.LowPart;
while(pCurrent != NULL) { LARGE_INTEGER liTemp2; // Used to avoid 64bit alignment problems
liTemp2.HighPart = pCurrent->CmResourceDescriptor.u.Memory.Start.HighPart; liTemp2.LowPart = pCurrent->CmResourceDescriptor.u.Memory.Start.LowPart;
if (liTemp2.QuadPart < liTemp.QuadPart) { pLast = pCurrent ; pCurrent = pCurrent->NextSame ; } else { break; } }
break; }
case CmResourceTypeDma :
pHead = &_SystemResourceList.DmaHead ; pTail = &_SystemResourceList.DmaTail ;
pCurrent = *pHead ; pLast = NULL ;
while(pCurrent != NULL && pCurrent->CmResourceDescriptor.u.Dma.Channel < pResource->u.Dma.Channel) { pLast = pCurrent ; pCurrent = pCurrent->NextSame ; }
break;
}
// Insert into...
//===============
if(*pHead == NULL) {
// ...empty list
//==========================
(*pHead) = pNewResource ; (*pTail) = pNewResource ; } else if(pLast == NULL) {
// ...beginning of list
//=================================
pNewResource->NextSame = pCurrent ; (*pHead) = pNewResource ; } else if(pCurrent == NULL) { // ...end of list
//=========================
pLast->NextSame = pNewResource ; (*pTail) = pNewResource ; } else { // ...middle of list
//==============================
pLast->NextSame = pNewResource ; pNewResource->NextSame = pCurrent ; } } #endif
// Helper function for converting strings to resource types
BOOL WINAPI StringFromInterfaceType( INTERFACE_TYPE it, CHString& strVal ) { //BOOL fReturn = TRUE;
//switch ( it )
//{
// case Internal: strVal = "INTERNAL"; break;
// case Isa: strVal = "ISA"; break;
// case Eisa: strVal = "EISA"; break;
// case MicroChannel: strVal = "MICROCHANNEL"; break;
// case TurboChannel: strVal = "TURBOCHANNEL"; break;
// case PCIBus: strVal = "PCI"; break;
// case VMEBus: strVal = "VME"; break;
// case NuBus: strVal = "NU"; break;
// case PCMCIABus: strVal = "PCMCIA"; break;
// case CBus: strVal = "INTERNAL"; break;
// case MPIBus: strVal = "INTERNAL"; break;
// case MPSABus: strVal = "MPSA"; break;
// case ProcessorInternal: strVal = "PROCESSORINTERNAL"; break;
// case InternalPowerBus: strVal = "INTERNALPOWER"; break;
// case PNPISABus: strVal = "PNPISA"; break;
// case PNPBus: strVal = "PNP"; break;
// default: fReturn = FALSE;
//}
if(it > InterfaceTypeUndefined && it < MaximumInterfaceType) { strVal = szBusType[it]; return TRUE; } else { return FALSE; } }
|