1063 lines
25 KiB
C++
1063 lines
25 KiB
C++
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <stdio.h>
|
|
#include <tchar.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <regstr.h>
|
|
#include <cfgmgr32.h>
|
|
#include "netinfo.h"
|
|
|
|
|
|
// Globals
|
|
|
|
DEV_INFO *g_pdiDevList; // Head of device list
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: (21) GetDevNodeInfoAndCreateNewDevInfoNode
|
|
|
|
Creates new list node, then gets registry and resource information for
|
|
a specific device and copies it into that node. Finally, adds new node
|
|
to beginning of linked list
|
|
|
|
Arguments:
|
|
|
|
dnDevNode: the device to find information about
|
|
szDevNodeID: the registry path name of the device
|
|
szEnumBuffer: name of enumerator this device is under
|
|
|
|
Return Value:
|
|
BOOL: TRUE if function succeeds, FALSE if not
|
|
|
|
--*/
|
|
BOOL GetDevNodeInfoAndCreateNewDevInfoNode(IN DEVNODE dnDevNode,
|
|
IN PTCHAR szDevNodeID,
|
|
IN PTCHAR szEnumBuffer)
|
|
{
|
|
LOG_CONF lcLogConf = 0, lcLogConfNew;
|
|
CONFIGRET cmret, cmret2;
|
|
|
|
PDEV_INFO pdiDevInfo=(PDEV_INFO)malloc(sizeof(DEV_INFO));
|
|
|
|
int i;
|
|
BOOL boolForcedFound = FALSE, boolAllocFound = FALSE;
|
|
USHORT ushLogConfType[4] = {BOOT_LOG_CONF, ALLOC_LOG_CONF, BASIC_LOG_CONF, FORCED_LOG_CONF};
|
|
|
|
if (pdiDevInfo == NULL)
|
|
goto RetFALSE;
|
|
|
|
|
|
// If this is not a PnP device, skip it
|
|
if (!lstrcmpi(szEnumBuffer, TEXT("Root"))) {
|
|
free(pdiDevInfo);
|
|
goto RetTRUE;
|
|
|
|
}
|
|
|
|
//
|
|
// Initialize fields inside the node
|
|
//
|
|
if (!InitializeInfoNode(pdiDevInfo, szDevNodeID, dnDevNode)) {
|
|
// This is a device we don't want to list. Skip it
|
|
free(pdiDevInfo);
|
|
goto RetTRUE;
|
|
}
|
|
|
|
|
|
for (i = 0; i < NUM_LOG_CONF_TYPES; i++) {
|
|
// Get logical configuration information
|
|
cmret = CM_Get_First_Log_Conf(&lcLogConfNew,
|
|
dnDevNode,
|
|
ushLogConfType[i]);
|
|
|
|
while (CR_SUCCESS == cmret) {
|
|
lcLogConf = lcLogConfNew;
|
|
|
|
if (ALLOC_LOG_CONF == ushLogConfType[i]) {
|
|
boolAllocFound = TRUE;
|
|
}
|
|
|
|
if (!(GetResDesList(pdiDevInfo, lcLogConf, ushLogConfType[i]))) {
|
|
goto RetFALSE;
|
|
}
|
|
|
|
cmret = CM_Get_Next_Log_Conf(&lcLogConfNew,
|
|
lcLogConf,
|
|
0);
|
|
|
|
cmret2 = CM_Free_Log_Conf_Handle(lcLogConf);
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// If device has no Alloc configurations, skip
|
|
// to the next device
|
|
//
|
|
if (!boolAllocFound) {
|
|
|
|
|
|
|
|
//free(pdiDevInfo);
|
|
//goto RetTRUE;
|
|
}
|
|
|
|
//
|
|
// Insert new pdiDevInfo into Linked List of DevNodes
|
|
//
|
|
if (g_pdiDevList == NULL) {
|
|
//
|
|
// DevList is empty
|
|
//
|
|
g_pdiDevList = pdiDevInfo;
|
|
} else {
|
|
//
|
|
// Add new pdiDevInfo to beginning of linked list
|
|
//
|
|
pdiDevInfo->Next = g_pdiDevList;
|
|
g_pdiDevList->Prev = pdiDevInfo;
|
|
|
|
g_pdiDevList = pdiDevInfo;
|
|
}
|
|
|
|
RetTRUE:
|
|
return TRUE;
|
|
|
|
RetFALSE:
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: (20) ParseEnumerator
|
|
|
|
Gets devices listed under enumerator name in registry
|
|
|
|
Arguments:
|
|
|
|
szEnumBuffer: the enumerator name
|
|
|
|
Return Value:
|
|
|
|
BOOL: TRUE if function succeeds, FALSE if not
|
|
|
|
--*/
|
|
BOOL
|
|
ParseEnumerator(IN PTCHAR szEnumBuffer)
|
|
{
|
|
|
|
PTCHAR szDevIDBuffer = NULL;
|
|
PTCHAR szDevNodeID = NULL;
|
|
ULONG ulDevIDBufferLen = 0, ulCount = 0, ulStart = 0;
|
|
CONFIGRET cmret = CR_SUCCESS;
|
|
DEVNODE dnDevNode;
|
|
BOOL bReturn = TRUE;
|
|
|
|
//
|
|
// Get buffer length
|
|
//
|
|
cmret = CM_Get_Device_ID_List_Size(&ulDevIDBufferLen,
|
|
szEnumBuffer,
|
|
CM_GETIDLIST_FILTER_ENUMERATOR);
|
|
|
|
if (CR_SUCCESS != cmret) {
|
|
//ErrorLog(20, TEXT("CM_Get_Device_ID_List_Size"), cmret, NULL);
|
|
bReturn = FALSE;
|
|
goto RetFALSE;
|
|
}
|
|
|
|
if ((szDevIDBuffer =(PTCHAR) malloc(sizeof(TCHAR) * ulDevIDBufferLen)) == NULL ||
|
|
(szDevNodeID =(PTCHAR) malloc(sizeof(TCHAR) * ulDevIDBufferLen)) == NULL) {
|
|
bReturn = FALSE;
|
|
goto RetFALSE;
|
|
}
|
|
|
|
//
|
|
// Get the Device ID List
|
|
//
|
|
cmret = CM_Get_Device_ID_List(szEnumBuffer,
|
|
szDevIDBuffer,
|
|
ulDevIDBufferLen,
|
|
CM_GETIDLIST_FILTER_ENUMERATOR);
|
|
|
|
if (CR_SUCCESS != cmret) {
|
|
//ErrorLog(20, TEXT("CM_Get_Device_ID_List"), cmret, NULL);
|
|
bReturn = FALSE;
|
|
goto RetFALSE;
|
|
}
|
|
|
|
//
|
|
// Note that ulDevIDBufferLen is a loose upper bound. The API may have
|
|
// returned a size greater than the actual size of the list of strings.
|
|
//
|
|
for (ulCount = 0; ulCount < ulDevIDBufferLen; ulCount++) {
|
|
ulStart = ulCount;
|
|
|
|
if (szDevIDBuffer[ulCount] != '\0') {
|
|
cmret = CM_Locate_DevNode(&dnDevNode,
|
|
szDevIDBuffer + ulCount,
|
|
CM_LOCATE_DEVNODE_NORMAL);
|
|
|
|
//
|
|
// Go to the next substring
|
|
//
|
|
while (szDevIDBuffer[ulCount] != TEXT('\0')) {
|
|
ulCount++;
|
|
|
|
}
|
|
// Stop when we reach the double-NULL terminator
|
|
|
|
if (szDevIDBuffer[ulCount+1] == TEXT('\0')) {
|
|
ulCount=ulDevIDBufferLen;
|
|
continue;
|
|
}
|
|
|
|
if (cmret == CR_SUCCESS) {
|
|
_tcsncpy(szDevNodeID, szDevIDBuffer + ulStart, ulDevIDBufferLen);
|
|
|
|
// Found the DevNode, so add its information to the device list
|
|
if (!(GetDevNodeInfoAndCreateNewDevInfoNode(dnDevNode,
|
|
szDevNodeID,
|
|
szEnumBuffer))) {
|
|
bReturn = FALSE;
|
|
goto RetFALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bReturn = TRUE;
|
|
RetFALSE:
|
|
// fix to rajeshm old code. Selective free bug number 137987
|
|
if (NULL != szDevIDBuffer)
|
|
free (szDevIDBuffer);
|
|
if (NULL != szDevNodeID)
|
|
free (szDevNodeID);
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
CollectDevData() {
|
|
|
|
|
|
CONFIGRET cmret = CR_SUCCESS;
|
|
ULONG ulIndexNum = 0;
|
|
ULONG ulEnumBufferLen = 0;
|
|
PTCHAR szEnumBuffer;
|
|
|
|
szEnumBuffer = (PTCHAR) malloc(sizeof(TCHAR) * MAX_DEVNODE_ID_LEN);
|
|
|
|
if (NULL == szEnumBuffer)
|
|
return;
|
|
|
|
for (ulIndexNum = 0; cmret == CR_SUCCESS; ulIndexNum++) {
|
|
|
|
ulEnumBufferLen = MAX_DEVNODE_ID_LEN;
|
|
cmret = CM_Enumerate_Enumerators( ulIndexNum,
|
|
szEnumBuffer,
|
|
&ulEnumBufferLen,
|
|
0);
|
|
if (cmret == CR_SUCCESS)
|
|
ParseEnumerator(szEnumBuffer);
|
|
}
|
|
|
|
free (szEnumBuffer);
|
|
}
|
|
|
|
|
|
|
|
BOOL CopyRegistryLine(IN DEVNODE dnDevNode,
|
|
IN ULONG ulPropertyType,
|
|
IN PDEV_INFO pdiDevInfo)
|
|
|
|
/*++
|
|
|
|
Routine Description: (22) CopyRegistryLine
|
|
|
|
Copies one specific string of registry data to new list node
|
|
|
|
Arguments:
|
|
|
|
dnDevNode: the device to get information about
|
|
ulpropertyType: which registry string to get
|
|
pdiDevInfo: the new list node
|
|
|
|
Return Value:
|
|
|
|
BOOL: TRUE if function succeeds, FALSE if not
|
|
|
|
--*/
|
|
{
|
|
ULONG ulRegDataLen = 0, ulRegDataType = 0;
|
|
CONFIGRET cmret = CR_SUCCESS;
|
|
PTCHAR szRegData = NULL;
|
|
|
|
//
|
|
// Get the length of the buffer don't bother checking return value
|
|
// If RegProperty doesn't exist, we'll just move on
|
|
//
|
|
CM_Get_DevNode_Registry_Property(dnDevNode,
|
|
ulPropertyType,
|
|
NULL,
|
|
NULL,
|
|
&ulRegDataLen,
|
|
0);
|
|
|
|
if (!ulRegDataLen ||
|
|
(szRegData = (PTCHAR) malloc(sizeof(TCHAR) * ulRegDataLen)) == NULL) {
|
|
goto RetFALSE;
|
|
}
|
|
|
|
//
|
|
// Now get the registry information
|
|
//
|
|
cmret = CM_Get_DevNode_Registry_Property( dnDevNode,
|
|
ulPropertyType,
|
|
&ulRegDataType,
|
|
szRegData,
|
|
&ulRegDataLen,
|
|
0);
|
|
|
|
if (CR_SUCCESS == cmret) {
|
|
if (!(CopyRegDataToDevInfoNode(pdiDevInfo,
|
|
ulPropertyType,
|
|
szRegData))) {
|
|
goto RetFALSE;
|
|
}
|
|
}
|
|
|
|
if (szRegData == NULL)
|
|
free (szRegData);
|
|
return TRUE;
|
|
|
|
|
|
RetFALSE:
|
|
return FALSE;
|
|
|
|
} /* CopyRegistryLine */
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: (23) CopyRegDataToDevInfoNode
|
|
|
|
Copies a registry string to a list node
|
|
|
|
Arguments:
|
|
|
|
pdiDevInfo: the new list node
|
|
ulPropertyType: which registry string to copy
|
|
szRegData: the data to be copied
|
|
|
|
Return Value:
|
|
|
|
BOOL: TRUE if function succeeds, FALSE if not
|
|
|
|
--*/
|
|
BOOL CopyRegDataToDevInfoNode(IN OUT PDEV_INFO pdiDevInfo,
|
|
IN ULONG ulPropertyType,
|
|
IN PTCHAR szRegData)
|
|
{
|
|
if (pdiDevInfo == NULL) {
|
|
goto RetFALSE;
|
|
}
|
|
|
|
switch (ulPropertyType) {
|
|
case CM_DRP_DEVICEDESC:
|
|
|
|
_tcsncpy(pdiDevInfo->szDescription, szRegData, MAX_PATH );
|
|
break;
|
|
|
|
case CM_DRP_HARDWAREID:
|
|
|
|
_tcsncpy(pdiDevInfo->szHardwareID, szRegData, MAX_PATH );
|
|
break;
|
|
|
|
case CM_DRP_SERVICE:
|
|
|
|
_tcsncpy(pdiDevInfo->szService, szRegData, MAX_PATH );
|
|
break;
|
|
|
|
case CM_DRP_CLASS:
|
|
|
|
_tcsncpy(pdiDevInfo->szClass, szRegData, MAX_PATH );
|
|
break;
|
|
|
|
case CM_DRP_MFG:
|
|
|
|
_tcsncpy(pdiDevInfo->szManufacturer, szRegData, MAX_PATH );
|
|
break;
|
|
|
|
case CM_DRP_CONFIGFLAGS:
|
|
|
|
_tcsncpy(pdiDevInfo->szConfigFlags, szRegData, MAX_PATH );
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
RetFALSE:
|
|
return FALSE;
|
|
|
|
} /* CopyRegDataToDevInfoNode */
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: (58) InitializeInfoNode
|
|
|
|
Initialized fields inside the new node
|
|
|
|
Arguments:
|
|
|
|
pdiDevInfo: the node
|
|
szDevNodeID: used to find the dnDevNode in the future
|
|
dnDevNode: the device we're storing information about
|
|
|
|
Return Value:
|
|
|
|
BOOL: TRUE if we should keep this node, FALSE if we should throw it away
|
|
|
|
--*/
|
|
BOOL InitializeInfoNode(IN PDEV_INFO pdiDevInfo,
|
|
IN PTCHAR szDevNodeID,
|
|
IN DEVNODE dnDevNode)
|
|
{
|
|
if (pdiDevInfo) {
|
|
pdiDevInfo->Next = NULL;
|
|
pdiDevInfo->Prev = NULL;
|
|
|
|
pdiDevInfo->szDevNodeID[0] = TEXT('\0');
|
|
pdiDevInfo->szDescription[0] = TEXT('\0');
|
|
pdiDevInfo->szHardwareID[0] = TEXT('\0');
|
|
pdiDevInfo->szService[0] = TEXT('\0');
|
|
pdiDevInfo->szClass[0] = TEXT('\0');
|
|
pdiDevInfo->szManufacturer[0] = TEXT('\0');
|
|
pdiDevInfo->szConfigFlags[0] = TEXT('\0');
|
|
pdiDevInfo->szFriendlyName[0] = TEXT('\0');
|
|
|
|
pdiDevInfo->boolSavedOrigConfiguration = FALSE;
|
|
pdiDevInfo->boolDisabled = FALSE;
|
|
|
|
pdiDevInfo->prddForcedResDesData = NULL;
|
|
pdiDevInfo->prddAllocResDesData = NULL;
|
|
pdiDevInfo->prddBasicResDesData = NULL;
|
|
pdiDevInfo->prddBootResDesData = NULL;
|
|
|
|
//
|
|
// Store devNodeID in pdiDevInfo to get handles to devnode in future
|
|
//
|
|
_tcsncpy(pdiDevInfo->szDevNodeID, szDevNodeID, MAX_PATH);
|
|
|
|
// Extract information from the registry about this DevNode
|
|
CopyRegistryLine(dnDevNode, CM_DRP_DEVICEDESC, pdiDevInfo);
|
|
CopyRegistryLine(dnDevNode, CM_DRP_HARDWAREID, pdiDevInfo);
|
|
CopyRegistryLine(dnDevNode, CM_DRP_SERVICE, pdiDevInfo);
|
|
CopyRegistryLine(dnDevNode, CM_DRP_CLASS, pdiDevInfo);
|
|
CopyRegistryLine(dnDevNode, CM_DRP_MFG, pdiDevInfo);
|
|
CopyRegistryLine(dnDevNode, CM_DRP_CONFIGFLAGS, pdiDevInfo);
|
|
|
|
RecordFriendlyName(pdiDevInfo);
|
|
}
|
|
|
|
//
|
|
// Check the friendly name to see if we want to throw this node away
|
|
//
|
|
if (strcmp(pdiDevInfo->szFriendlyName, "STORAGE/Volume") == 0 ||
|
|
strcmp(pdiDevInfo->szFriendlyName, "Unknown Device") == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* InitializeInfoNode */
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: (57) RecordFriendlyName
|
|
|
|
Finds the best user friendly name for this device
|
|
|
|
Arguments:
|
|
|
|
pdiDevInfo: node containing all possible names
|
|
|
|
Return Value:
|
|
|
|
void
|
|
|
|
--*/
|
|
void
|
|
RecordFriendlyName(IN PDEV_INFO pdiDevInfo)
|
|
{
|
|
|
|
if (pdiDevInfo) {
|
|
|
|
if (pdiDevInfo->szDescription && pdiDevInfo->szDescription[0] != TEXT('\0'))
|
|
|
|
_tcsncpy(pdiDevInfo->szFriendlyName, pdiDevInfo->szDescription, MAX_PATH );
|
|
|
|
else if (pdiDevInfo->szHardwareID && pdiDevInfo->szHardwareID[0] != TEXT('\0'))
|
|
|
|
_tcsncpy(pdiDevInfo->szFriendlyName, pdiDevInfo->szHardwareID, MAX_PATH);
|
|
|
|
else if (pdiDevInfo->szManufacturer && pdiDevInfo->szManufacturer[0] != TEXT('\0'))
|
|
|
|
_tcsncpy(pdiDevInfo->szFriendlyName, pdiDevInfo->szHardwareID, MAX_PATH);
|
|
|
|
else if (pdiDevInfo->szService && pdiDevInfo->szService[0] != TEXT('\0'))
|
|
|
|
_tcsncpy(pdiDevInfo->szFriendlyName, pdiDevInfo->szService, MAX_PATH);
|
|
|
|
else if (pdiDevInfo->szClass && pdiDevInfo->szClass[0] != TEXT('\0'))
|
|
|
|
_tcsncpy(pdiDevInfo->szFriendlyName, pdiDevInfo->szClass, MAX_PATH);
|
|
|
|
else
|
|
_tcscpy(pdiDevInfo->szFriendlyName, TEXT("Unknown Device"));
|
|
}
|
|
} /* RecordFriendlyName */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: (24) GetResDesList
|
|
|
|
Creates new resource data node and copies resource information to that node
|
|
|
|
Arguments:
|
|
|
|
pdiDevInfo: the list node which will contain the new resource node
|
|
lcLogConf: the logical configuration information
|
|
ulLogConfType: FORCED, ALLOC, BOOT, or BASIC logical configuration
|
|
|
|
Return Value:
|
|
|
|
BOOL: TRUE if function succeeds, FALSE if not
|
|
|
|
--*/
|
|
BOOL
|
|
GetResDesList(IN OUT PDEV_INFO pdiDevInfo,
|
|
IN LOG_CONF lcLogConf,
|
|
IN ULONG ulLogConfType)
|
|
{
|
|
CONFIGRET cmret, cmret2;
|
|
RES_DES rdResDes = 0, rdResDesNew;
|
|
RESOURCEID ridResourceID = 0;
|
|
PRES_DES_DATA prddResDesData;
|
|
|
|
prddResDesData = (PRES_DES_DATA)malloc(sizeof(RES_DES_DATA));
|
|
|
|
if (prddResDesData == NULL)
|
|
goto c0;
|
|
|
|
prddResDesData->Next = NULL;
|
|
prddResDesData->Prev = NULL;
|
|
prddResDesData->pmresMEMResource = NULL;
|
|
prddResDesData->piresIOResource = NULL;
|
|
prddResDesData->pdresDMAResource = NULL;
|
|
prddResDesData->pqresIRQResource = NULL;
|
|
|
|
|
|
cmret = CM_Get_Next_Res_Des(&rdResDesNew,
|
|
lcLogConf,
|
|
ResType_All,
|
|
&ridResourceID,
|
|
0);
|
|
|
|
//
|
|
// Go through each resource type and copy data to new node
|
|
//
|
|
while (CR_SUCCESS == cmret) {
|
|
rdResDes = rdResDesNew;
|
|
|
|
if (ridResourceID >= ResType_Mem && ridResourceID <= ResType_IRQ) {
|
|
if (!(ProcessResDesInfo(prddResDesData,
|
|
rdResDes,
|
|
ridResourceID))) {
|
|
goto c1;
|
|
}
|
|
}
|
|
|
|
cmret = CM_Get_Next_Res_Des(&rdResDesNew,
|
|
rdResDes,
|
|
ResType_All,
|
|
&ridResourceID,
|
|
0);
|
|
|
|
cmret2 = CM_Free_Res_Des_Handle(rdResDes);
|
|
|
|
if (cmret2 != CR_SUCCESS) {
|
|
//ErrorLog(24, TEXT("CM_Free_Res_Des_Handle"), cmret2, NULL);
|
|
}
|
|
}
|
|
|
|
// Add the new node to the linked list
|
|
switch (ulLogConfType) {
|
|
case FORCED_LOG_CONF:
|
|
|
|
if (!pdiDevInfo->prddForcedResDesData) {
|
|
//
|
|
// This is the first entry into the linked list
|
|
//
|
|
pdiDevInfo->prddForcedResDesData = prddResDesData;
|
|
} else {
|
|
//
|
|
// Add new node to beginning of linked list
|
|
//
|
|
prddResDesData->Next = pdiDevInfo->prddForcedResDesData;
|
|
pdiDevInfo->prddForcedResDesData->Prev = prddResDesData;
|
|
|
|
pdiDevInfo->prddForcedResDesData = prddResDesData;
|
|
}
|
|
break;
|
|
|
|
case ALLOC_LOG_CONF:
|
|
|
|
if (!pdiDevInfo->prddAllocResDesData) {
|
|
//
|
|
// This is the first entry into the linked list
|
|
//
|
|
pdiDevInfo->prddAllocResDesData = prddResDesData;
|
|
} else {
|
|
//
|
|
// Add new node to beginning of linked list
|
|
//
|
|
prddResDesData->Next = pdiDevInfo->prddAllocResDesData;
|
|
pdiDevInfo->prddAllocResDesData->Prev = prddResDesData;
|
|
|
|
pdiDevInfo->prddAllocResDesData = prddResDesData;
|
|
}
|
|
break;
|
|
|
|
case BASIC_LOG_CONF:
|
|
|
|
if (!pdiDevInfo->prddBasicResDesData) {
|
|
//
|
|
// This is the first entry into the linked list
|
|
//
|
|
pdiDevInfo->prddBasicResDesData = prddResDesData;
|
|
} else {
|
|
//
|
|
// Add new node to beginning of linked list
|
|
//
|
|
prddResDesData->Next = pdiDevInfo->prddBasicResDesData;
|
|
pdiDevInfo->prddBasicResDesData->Prev = prddResDesData;
|
|
|
|
pdiDevInfo->prddBasicResDesData = prddResDesData;
|
|
}
|
|
break;
|
|
|
|
case BOOT_LOG_CONF:
|
|
|
|
if (!pdiDevInfo->prddBootResDesData) {
|
|
//
|
|
// This is the first entry into the linked list
|
|
//
|
|
pdiDevInfo->prddBootResDesData = prddResDesData;
|
|
} else {
|
|
//
|
|
// Add new node to beginning of linked list
|
|
//
|
|
prddResDesData->Next = pdiDevInfo->prddBootResDesData;
|
|
pdiDevInfo->prddBootResDesData->Prev = prddResDesData;
|
|
|
|
pdiDevInfo->prddBootResDesData = prddResDesData;
|
|
}
|
|
break;
|
|
default:
|
|
goto c1;
|
|
}
|
|
return TRUE;
|
|
|
|
c1:
|
|
free(prddResDesData);
|
|
c0:
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
/* GetResDestList */
|
|
|
|
/*++
|
|
|
|
Routine Description: (25) ProcessResDesInfo
|
|
|
|
Gets information for one resource descriptor
|
|
|
|
Arguments:
|
|
|
|
prddResDesData: the new resource data node receiving the info
|
|
rdResDes: the resource descriptor containing the info
|
|
ridResourceID: tells the resource type (DMA, IO, MEM, IRQ, or CS)
|
|
|
|
Return Value:
|
|
|
|
BOOL: TRUE if function succeeds, FALSE if not
|
|
|
|
--*/
|
|
BOOL
|
|
ProcessResDesInfo(IN OUT PRES_DES_DATA prddResDesData,
|
|
IN RES_DES rdResDes,
|
|
IN RESOURCEID ridResourceID)
|
|
{
|
|
PVOID pvResDesDataBuffer = NULL;
|
|
ULONG ulResDesDataBufferLen;
|
|
CONFIGRET cmret;
|
|
|
|
cmret = CM_Get_Res_Des_Data_Size(&ulResDesDataBufferLen,
|
|
rdResDes,
|
|
0);
|
|
|
|
if (CR_SUCCESS != cmret) {
|
|
//ErrorLog(25, TEXT("CM_Get_Res_Des_Data_Size"), cmret, NULL);
|
|
goto RetFALSE;
|
|
}
|
|
|
|
if ((pvResDesDataBuffer = malloc(sizeof(PVOID) * ulResDesDataBufferLen))
|
|
== NULL) {
|
|
// Log(25, SEV2, TEXT("resDesDataBuffer malloc size of %d failed."),
|
|
// ulResDesDataBufferLen);
|
|
goto RetFALSE;
|
|
}
|
|
|
|
//
|
|
// Get the data
|
|
//
|
|
cmret = CM_Get_Res_Des_Data(rdResDes,
|
|
pvResDesDataBuffer,
|
|
ulResDesDataBufferLen,
|
|
0);
|
|
|
|
if (CR_SUCCESS != cmret) {
|
|
//ErrorLog(25, TEXT("CM_Get_Res_Des_Data"), cmret, NULL);
|
|
goto RetFALSE;
|
|
}
|
|
|
|
//
|
|
// Copy data into ResDesData node
|
|
//
|
|
switch (ridResourceID) {
|
|
case ResType_Mem:
|
|
|
|
prddResDesData->pmresMEMResource = (PMEM_RESOURCE)pvResDesDataBuffer;
|
|
break;
|
|
|
|
case ResType_IO:
|
|
|
|
prddResDesData->piresIOResource = (PIO_RESOURCE)pvResDesDataBuffer;
|
|
break;
|
|
|
|
case ResType_DMA:
|
|
|
|
prddResDesData->pdresDMAResource = (PDMA_RESOURCE)pvResDesDataBuffer;
|
|
break;
|
|
|
|
case ResType_IRQ:
|
|
|
|
prddResDesData->pqresIRQResource = (PIRQ_RESOURCE)pvResDesDataBuffer;
|
|
break;
|
|
|
|
default:
|
|
|
|
// Log(25, SEV2, TEXT("Illegal ResourceID - %ul"), ridResourceID);
|
|
goto RetFALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
RetFALSE:
|
|
return FALSE;
|
|
|
|
} /* ProcessResDesInfo */
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: (26) UpdateDeviceList
|
|
|
|
Frees resource information for all devices and then collects the
|
|
information again
|
|
|
|
Arguments:
|
|
|
|
none (g_pdiDevList is global head of device list)
|
|
|
|
Return Value:
|
|
|
|
BOOL: TRUE if function succeeds, FALSE if not
|
|
|
|
--*/
|
|
BOOL UpdateDeviceList()
|
|
{
|
|
PDEV_INFO pdiTmpDevInfo;
|
|
|
|
pdiTmpDevInfo = g_pdiDevList;
|
|
|
|
//
|
|
// Go through linked list and delete each node's ResDes lists
|
|
//
|
|
while (pdiTmpDevInfo) {
|
|
if (pdiTmpDevInfo->prddForcedResDesData) {
|
|
DeleteResDesDataNode(pdiTmpDevInfo->prddForcedResDesData);
|
|
pdiTmpDevInfo->prddForcedResDesData = NULL;
|
|
}
|
|
|
|
if (pdiTmpDevInfo->prddAllocResDesData) {
|
|
DeleteResDesDataNode(pdiTmpDevInfo->prddAllocResDesData);
|
|
pdiTmpDevInfo->prddAllocResDesData = NULL;
|
|
}
|
|
|
|
if (pdiTmpDevInfo->prddBasicResDesData) {
|
|
DeleteResDesDataNode(pdiTmpDevInfo->prddBasicResDesData);
|
|
pdiTmpDevInfo->prddBasicResDesData = NULL;
|
|
}
|
|
|
|
if (pdiTmpDevInfo->prddBootResDesData) {
|
|
DeleteResDesDataNode(pdiTmpDevInfo->prddBootResDesData);
|
|
pdiTmpDevInfo->prddBootResDesData = NULL;
|
|
}
|
|
|
|
pdiTmpDevInfo = pdiTmpDevInfo->Next;
|
|
}
|
|
|
|
pdiTmpDevInfo = g_pdiDevList;
|
|
|
|
//
|
|
// Recreate the ResDesLists for each node
|
|
//
|
|
while (pdiTmpDevInfo) {
|
|
if (!(RecreateResDesList(pdiTmpDevInfo, FORCED_LOG_CONF)))
|
|
goto RetFALSE;
|
|
|
|
if (!(RecreateResDesList(pdiTmpDevInfo, ALLOC_LOG_CONF)))
|
|
goto RetFALSE;
|
|
|
|
if (!(RecreateResDesList(pdiTmpDevInfo, BASIC_LOG_CONF)))
|
|
goto RetFALSE;
|
|
|
|
if (!(RecreateResDesList(pdiTmpDevInfo, BOOT_LOG_CONF)))
|
|
goto RetFALSE;
|
|
|
|
pdiTmpDevInfo = pdiTmpDevInfo->Next;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
RetFALSE:
|
|
return FALSE;
|
|
|
|
} /* UpdateDeviceList */
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: (27) DeleteResDesDataNode
|
|
|
|
Deletes a string of RES_DES_DATA structures
|
|
|
|
Arguments:
|
|
|
|
prddTmpResDes: the head of the linked list
|
|
|
|
Return Value:
|
|
|
|
void
|
|
|
|
--*/
|
|
void
|
|
DeleteResDesDataNode(IN PRES_DES_DATA prddTmpResDes)
|
|
{
|
|
PRES_DES_DATA prddNextResDes;
|
|
|
|
while (prddTmpResDes) {
|
|
prddNextResDes = prddTmpResDes->Next;
|
|
|
|
free (prddTmpResDes);
|
|
prddTmpResDes = prddNextResDes;
|
|
}
|
|
|
|
} /* DeleteResDesDataNode */
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: (56) CopyDataToLogConf
|
|
|
|
Calls CM_Add_Res_Des to add a resDes to a lcLogConf
|
|
|
|
Arguments:
|
|
|
|
lcLogConf: the lcLogConf receiving the resDes
|
|
ridResType: ResType_Mem, IO, DMA or IRQ
|
|
pvResData: the new data
|
|
ulResourceLen: size of the data
|
|
|
|
Return Value:
|
|
|
|
BOOL: TRUE if the CM call succeeds, FALSE if not
|
|
|
|
--*/
|
|
BOOL
|
|
CopyDataToLogConf(IN LOG_CONF lcLogConf,
|
|
IN RESOURCEID ridResType,
|
|
IN PVOID pvResData,
|
|
IN ULONG ulResourceLen)
|
|
{
|
|
CONFIGRET cmret;
|
|
RES_DES rdResDes;
|
|
|
|
//
|
|
// Copy the data to the logConf
|
|
//
|
|
cmret = CM_Add_Res_Des(&rdResDes,
|
|
lcLogConf,
|
|
ridResType,
|
|
pvResData,
|
|
ulResourceLen,
|
|
0);
|
|
|
|
if (CR_SUCCESS != cmret) {
|
|
|
|
goto RetFALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
RetFALSE:
|
|
return FALSE;
|
|
|
|
} /* CopyDataToLogConf */
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: (28) RecreateResDesList
|
|
|
|
Uses CM calls to find ResDes information and creates linked list
|
|
of this information inside of given DEV_INFO
|
|
|
|
Arguments:
|
|
|
|
pdiTmpDevInfo: the node receiving the information
|
|
ulLogConfType: the LogConf type (FORCED_LOG_CONF,
|
|
ALLOC_LOG_CONF,
|
|
BASIC_LOG_CONF,
|
|
BOOT_LOG_CONF)
|
|
|
|
Return Value:
|
|
|
|
BOOL: TRUE if function succeeds, FALSE if not
|
|
|
|
--*/
|
|
BOOL
|
|
RecreateResDesList(IN OUT PDEV_INFO pdiTmpDevInfo,
|
|
IN ULONG ulLogConfType)
|
|
{
|
|
CONFIGRET cmret, cmret2;
|
|
DEVNODE dnDevNode;
|
|
LOG_CONF lcLogConf, lcLogConfNew;
|
|
|
|
//
|
|
// Get handle to the devnode
|
|
//
|
|
cmret = CM_Locate_DevNode(&dnDevNode,
|
|
pdiTmpDevInfo->szDevNodeID,
|
|
CM_LOCATE_DEVNODE_NORMAL);
|
|
|
|
if (CR_SUCCESS != cmret) {
|
|
//ErrorLog(28, TEXT("CM_Locate_DevNode"), cmret, NULL);
|
|
goto RetFALSE;
|
|
}
|
|
|
|
//
|
|
// Get logical configuration information
|
|
//
|
|
cmret = CM_Get_First_Log_Conf(&lcLogConfNew,
|
|
dnDevNode,
|
|
ulLogConfType);
|
|
|
|
while (CR_SUCCESS == cmret) {
|
|
lcLogConf = lcLogConfNew;
|
|
|
|
if (!(GetResDesList(pdiTmpDevInfo, lcLogConf, ulLogConfType))) {
|
|
goto RetFALSE;
|
|
}
|
|
|
|
cmret = CM_Get_Next_Log_Conf(&lcLogConfNew,
|
|
lcLogConf,
|
|
0);
|
|
|
|
cmret2 = CM_Free_Log_Conf_Handle(lcLogConf);
|
|
|
|
if (CR_SUCCESS != cmret2) {
|
|
//ErrorLog(28, TEXT("CM_Free_Log_Conf"), cmret2, NULL);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
RetFALSE:
|
|
return FALSE;
|
|
|
|
} /* RecreateResDesList */
|
|
|
|
|
|
|
|
|
|
|
|
void Cleanup()
|
|
{
|
|
PDEV_INFO pdiDevInfo = g_pdiDevList;
|
|
PDEV_INFO pdiNextInfoNode;
|
|
|
|
|
|
|
|
while (pdiDevInfo) {
|
|
|
|
pdiNextInfoNode = pdiDevInfo->Next;
|
|
|
|
DeleteResDesDataNode(pdiDevInfo->prddForcedResDesData);
|
|
DeleteResDesDataNode(pdiDevInfo->prddAllocResDesData);
|
|
DeleteResDesDataNode(pdiDevInfo->prddBasicResDesData);
|
|
DeleteResDesDataNode(pdiDevInfo->prddBootResDesData);
|
|
|
|
free(pdiDevInfo);
|
|
|
|
pdiDevInfo = pdiNextInfoNode;
|
|
}
|
|
|
|
} /* Cleanup */
|