1149 lines
26 KiB
C
1149 lines
26 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 "pnpstuff.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;
|
|
BOOL boolForced;
|
|
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;
|
|
|
|
} /* GetDevNodeInfoAndCreateNewDevInfoNode */
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
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;
|
|
|
|
//
|
|
// 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);
|
|
goto RetFALSE;
|
|
}
|
|
|
|
if ((szDevIDBuffer = malloc(sizeof(TCHAR) * ulDevIDBufferLen)) == NULL ||
|
|
(szDevNodeID = malloc(sizeof(TCHAR) * ulDevIDBufferLen)) == NULL)
|
|
{
|
|
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);
|
|
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)
|
|
{
|
|
wsprintf(szDevNodeID, TEXT("%s"), szDevIDBuffer + ulStart);
|
|
|
|
//
|
|
// Found the DevNode, so add its information to the device list
|
|
//
|
|
if (!(GetDevNodeInfoAndCreateNewDevInfoNode(dnDevNode,
|
|
szDevNodeID,
|
|
szEnumBuffer)))
|
|
{
|
|
goto RetFALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
RetFALSE:
|
|
|
|
return FALSE;
|
|
|
|
} /* Parse Enumerator */
|
|
|
|
|
|
|
|
|
|
void CollectDevData()
|
|
{
|
|
CONFIGRET cmret = CR_SUCCESS;
|
|
ULONG ulIndexNum = 0;
|
|
ULONG ulEnumBufferLen = 0;
|
|
PTCHAR szEnumBuffer;
|
|
|
|
szEnumBuffer = malloc(sizeof(TCHAR) * MAX_DEVNODE_ID_LEN);
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
} /* CollectDevData */
|
|
|
|
|
|
|
|
/*++
|
|
|
|
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
|
|
|
|
--*/
|
|
BOOL CopyRegistryLine(IN DEVNODE dnDevNode,
|
|
IN ULONG ulPropertyType,
|
|
IN PDEV_INFO pdiDevInfo)
|
|
{
|
|
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 = 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;
|
|
}
|
|
}
|
|
|
|
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:
|
|
|
|
wsprintf(pdiDevInfo->szDescription, TEXT("%s"), szRegData);
|
|
break;
|
|
|
|
case CM_DRP_HARDWAREID:
|
|
|
|
wsprintf(pdiDevInfo->szHardwareID, TEXT("%s"), szRegData);
|
|
break;
|
|
|
|
case CM_DRP_SERVICE:
|
|
|
|
wsprintf(pdiDevInfo->szService, TEXT("%s"), szRegData);
|
|
break;
|
|
|
|
case CM_DRP_CLASS:
|
|
|
|
wsprintf(pdiDevInfo->szClass, TEXT("%s"), szRegData);
|
|
break;
|
|
|
|
case CM_DRP_MFG:
|
|
|
|
wsprintf(pdiDevInfo->szManufacturer, TEXT("%s"), szRegData);
|
|
break;
|
|
|
|
case CM_DRP_CONFIGFLAGS:
|
|
|
|
wsprintf(pdiDevInfo->szConfigFlags, TEXT("%s"), szRegData);
|
|
break;
|
|
|
|
|
|
|
|
// Log(23, SEV2, TEXT("Invalid property type"));
|
|
}
|
|
|
|
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] = '\0';
|
|
pdiDevInfo->szDescription[0] = '\0';
|
|
pdiDevInfo->szHardwareID[0] = '\0';
|
|
pdiDevInfo->szService[0] = '\0';
|
|
pdiDevInfo->szClass[0] = '\0';
|
|
pdiDevInfo->szManufacturer[0] = '\0';
|
|
pdiDevInfo->szConfigFlags[0] = '\0';
|
|
pdiDevInfo->szFriendlyName[0] = '\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
|
|
//
|
|
wsprintf(pdiDevInfo->szDevNodeID, TEXT("%s"), szDevNodeID);
|
|
|
|
//
|
|
// 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] != '\0')
|
|
{
|
|
wsprintf(pdiDevInfo->szFriendlyName, TEXT("%s"),
|
|
pdiDevInfo->szDescription);
|
|
}
|
|
else if (pdiDevInfo->szHardwareID &&
|
|
pdiDevInfo->szHardwareID[0] != '\0')
|
|
{
|
|
wsprintf(pdiDevInfo->szFriendlyName, TEXT("%s"),
|
|
pdiDevInfo->szHardwareID);
|
|
}
|
|
else if (pdiDevInfo->szManufacturer &&
|
|
pdiDevInfo->szManufacturer[0] != '\0')
|
|
{
|
|
wsprintf(pdiDevInfo->szFriendlyName, TEXT("%s"),
|
|
pdiDevInfo->szHardwareID);
|
|
}
|
|
else if (pdiDevInfo->szService &&
|
|
pdiDevInfo->szService[0] != '\0')
|
|
{
|
|
wsprintf(pdiDevInfo->szFriendlyName, TEXT("%s"),
|
|
pdiDevInfo->szService);
|
|
}
|
|
else if (pdiDevInfo->szClass &&
|
|
pdiDevInfo->szClass[0] != '\0')
|
|
{
|
|
wsprintf(pdiDevInfo->szFriendlyName, TEXT("%s"),
|
|
pdiDevInfo->szClass);
|
|
}
|
|
else
|
|
{
|
|
wsprintf(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)
|
|
{
|
|
// Log(24, SEV2, TEXT("ResDesData malloc failed."));
|
|
goto RetFALSE;
|
|
}
|
|
|
|
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 RetFALSE;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
//
|
|
// **** change this by making resDesData = pdiDevInfo->----ResDesDAta
|
|
// and merging into one code
|
|
//
|
|
|
|
//
|
|
// 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:
|
|
|
|
// Log(24, SEV2, TEXT("Illegal LogConfType\n - %ul"), ulLogConfType);
|
|
goto RetFALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
RetFALSE:
|
|
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 */
|