windows-nt/Source/XPSP1/NT/base/ntsetup/opktools/syslib/devids.c
2020-09-26 16:20:57 +08:00

436 lines
15 KiB
C

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
devids.c
Abstract:
Builds a list of device ID and INF name pairs, based on a device class, and or
INI file list.
The list will be built as follows:
If the list exists in the specified INI file, then the INI file will be used.
If the specified INI file section exists, but is empty, then the local INF files
will be used
If the specified INI section does not exists, then no list will be built
Author:
Donald McNamara (donaldm) 02/08/2000
Revision History:
--*/
#include "pch.h"
#include <spsyslib.h>
/*++
===============================================================================
Routine Description:
BOOL bIniSectionExists
This routine will determine if the specified INI sections exists in the
specificed INI file
Arguments:
lpszSectionName - The section name to look for
lpszIniFile - The INI file to search
Return Value:
TRUE if the section name exists
FALSE if the section name does not exist
FALSE and LastError != 0 if there was a critical failure.
===============================================================================
--*/
#ifndef LOG
#define LogFactoryInstallError
#endif
// ISSUE-2002/03/27-acosma,robertko - Check for NULL input parameters.
//
BOOL bINISectionExists
(
LPTSTR lpszSectionName,
LPTSTR lpszIniFile
)
{
BOOL bRet = FALSE; // Assume it does not exists
LPTSTR lpBuffer;
LPTSTR lpNew;
LPTSTR lpSections;
DWORD dwSectionLen;
DWORD dwBufferSize;
DWORD dwResult;
SetLastError(0); // Assume no errors so far
// Allocate a buffer to hold the section names
if(lpBuffer = (LPTSTR)LocalAlloc(LPTR, (INIBUF_SIZE*sizeof(TCHAR))))
{
dwBufferSize = INIBUF_SIZE;
}
else
{
LogFactoryInstallError(TEXT("FACTORY:: Failed to allocate a buffer for reading the WINBOM file"));
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Clean0;
}
while((dwResult = GetPrivateProfileSectionNames(lpBuffer,
dwBufferSize,
lpszIniFile)) == (dwBufferSize-2))
{
if(lpNew = LocalReAlloc(lpBuffer,
((dwBufferSize+INIBUF_GROW)*sizeof(TCHAR)),
LMEM_MOVEABLE))
{
lpBuffer = lpNew;
dwBufferSize += INIBUF_GROW;
}
else
{
LogFactoryInstallError(TEXT("FACTORY:: Failed to Re-allocate a buffer for reading the WINBOM file"));
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Clean0;
}
}
// Enumerate all sections
for(lpSections = lpBuffer; *lpSections; lpSections+=dwSectionLen)
{
dwSectionLen = lstrlen(lpSections)+1;
if (lstrcmpi(lpSections, lpszSectionName) == 0)
{
bRet = TRUE;
break;
}
}
Clean0:
if (lpBuffer)
{
LocalFree(lpBuffer);
}
return bRet;
}
/*++
===============================================================================
Routine Description:
BOOL BuildDeviceIDList
This routine will build the list of device IDs
Arguments:
lpszSectionName - The section name that might contain a list of device IDs and INFs
lpszIniFile - The INI file to search
lpDeviceClassGUID - The device class to use to generate a list of all possible IDs
lpDeviceIDList - A pointer to be allocated and filled in with the list of IDs
lpdwNumDeviceIDs - A pointer to a DWORD that will recieve the number of IDs found
bForceIDScan - If TRUE a scan of IDs will be forced, even if the Section name is
not empty.
bForceAlwaysSecExist - Do a Scan for all IDs even if the section name does not exist.
Return Value:
TRUE if the list is build with no problem, or the list is empty because there
was no INI file section. lpdwNumDeviceIDs is valid in this case
FALSE if the list cannot be built.
===============================================================================
--*/
// ISSUE-2002/03/27-acosma,robertko - Check for NULL input parameters.
//
BOOL BuildDeviceIDList
(
LPTSTR lpszSectionName,
LPTSTR lpszIniFileName,
LPGUID lpDeviceClassGUID,
LPDEVIDLIST *lplpDeviceIDList,
LPDWORD lpdwNumDeviceIDs,
BOOL bForceIDScan,
BOOL bForceAlwaysSecExist
)
{
BOOL bRet = TRUE;
LPTSTR lpNew;
LPTSTR lpBuffer;
LPTSTR lpKeys;
DWORD dwBufferSize;
DWORD dwKeyLen;
DWORD dwResult;
HDEVINFO DeviceInfoSet;
SP_DRVINFO_DATA DrvInfoData;
SP_DEVINSTALL_PARAMS DeviceInstallParams;
PSP_DRVINFO_DETAIL_DATA lpDrvInfoDetailData;
DWORD cbBytesNeeded = 0;
int i;
LPTSTR lpszHwIDs;
LPDEVIDLIST lpDevIDList;
DWORD dwSizeDevIDList;
WCHAR szINFFileName[MAX_PATH];
// Allocate a buffer to hold the section names
if(lpBuffer = (LPTSTR)LocalAlloc(LPTR, (INIBUF_SIZE*sizeof(TCHAR))))
{
dwBufferSize = INIBUF_SIZE;
}
else
{
LogFactoryInstallError(TEXT("FACTORY:: Failed to allocate a buffer for reading the WINBOM file"));
bRet = FALSE;
goto Clean1;
}
// Iniitalize the number of device ID's found
*lpdwNumDeviceIDs = 0;
// See if the INI section exists. We don't do anything if it does not
if (bForceAlwaysSecExist || bINISectionExists(lpszSectionName, lpszIniFileName))
{
// Allocate the Initial ID array
*lplpDeviceIDList = LocalAlloc(LPTR, DEVID_ARRAY_SIZE * sizeof(DEVIDLIST));
lpDevIDList = *lplpDeviceIDList;
dwSizeDevIDList = DEVID_ARRAY_SIZE;
// Make sure there was not an error
if (!lpDevIDList)
{
LogFactoryInstallError(TEXT("FACTORY:: Failed to allocate a buffer for reading the WINBOM file"));
bRet = FALSE;
goto Clean1;
}
dwResult = GetPrivateProfileString(lpszSectionName,
NULL, // Get all keys
TEXT(""),
lpBuffer,
dwBufferSize,
lpszIniFileName);
if (bForceIDScan || dwResult == 0)
{
// Allocate a DeviceInfo Set, for the specific device class GUID
DeviceInfoSet = SetupDiCreateDeviceInfoList(lpDeviceClassGUID, NULL);
if(DeviceInfoSet == INVALID_HANDLE_VALUE)
{
bRet = FALSE;
goto Clean1;
}
// OR in the DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE flag to ensure we populate
// the list with all of the device id's
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if (SetupDiGetDeviceInstallParams(DeviceInfoSet,
NULL,
&DeviceInstallParams))
{
DeviceInstallParams.FlagsEx |= DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE;
SetupDiSetDeviceInstallParams(DeviceInfoSet,
NULL,
&DeviceInstallParams);
}
if (!SetupDiBuildDriverInfoList(DeviceInfoSet, NULL, SPDIT_CLASSDRIVER))
{
bRet = FALSE;
goto Clean1;
}
i = 0;
DrvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
while (SetupDiEnumDriverInfo(DeviceInfoSet,
NULL,
SPDIT_CLASSDRIVER,
i,
&DrvInfoData))
{
if (!SetupDiGetDriverInfoDetail(DeviceInfoSet,
NULL,
&DrvInfoData,
NULL,
0,
&cbBytesNeeded))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
continue;
}
}
lpDrvInfoDetailData = LocalAlloc(LPTR, cbBytesNeeded);
lpDrvInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
lpDrvInfoDetailData->HardwareID[0] = (TCHAR)NULL;
lpDrvInfoDetailData->CompatIDsLength = 0;
if (!SetupDiGetDriverInfoDetail(DeviceInfoSet,
NULL,
&DrvInfoData,
lpDrvInfoDetailData,
cbBytesNeeded,
NULL))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
LocalFree(lpDrvInfoDetailData);
continue;
}
}
//
// Init
//
lpDevIDList[*lpdwNumDeviceIDs].szHardwareID[0] = _T('\0');
lpDevIDList[*lpdwNumDeviceIDs].szCompatibleID[0] = _T('\0');
//
// Process only devices with valid HardWareID
//
if (lpDrvInfoDetailData->HardwareID[0] || lpDrvInfoDetailData->CompatIDsLength)
{
// Copy the HW ID
if (lpDrvInfoDetailData->HardwareID[0])
lstrcpy(lpDevIDList[*lpdwNumDeviceIDs].szHardwareID, lpDrvInfoDetailData->HardwareID);
// Copy the Compat ID
if (lpDrvInfoDetailData->CompatIDsLength)
{
lstrcpyn(lpDevIDList[*lpdwNumDeviceIDs].szCompatibleID,
(LPCTSTR)lpDrvInfoDetailData->HardwareID + lpDrvInfoDetailData->CompatIDsOffset,
lpDrvInfoDetailData->CompatIDsLength);
}
// Copy the INF file name
lstrcpy(lpDevIDList[*lpdwNumDeviceIDs].szINFFileName, lpDrvInfoDetailData->InfFileName);
//
// Increment PnP devices count
//
++(*lpdwNumDeviceIDs);
// See if the device ID buffer needs to be reallocated
if (*lpdwNumDeviceIDs == dwSizeDevIDList)
{
if(lpNew = LocalReAlloc(*lplpDeviceIDList,
((dwSizeDevIDList + DEVID_ARRAY_GROW)*sizeof(DEVIDLIST)),
LMEM_MOVEABLE))
{
*lplpDeviceIDList = (LPDEVIDLIST)lpNew;
lpDevIDList = *lplpDeviceIDList;
dwSizeDevIDList += DEVID_ARRAY_GROW;
}
else
{
LogFactoryInstallError(TEXT("FACTORY:: Failed to Re-allocate a buffer for reading the WINBOM file"));
bRet = FALSE;
goto Clean1;
}
}
}
LocalFree(lpDrvInfoDetailData);
++i;
}
}
else
{
// See if we got the whole section, and while we don't keep
// making lpbuffer biffer
while (dwResult == (dwBufferSize-2))
{
if(lpNew = LocalReAlloc(lpBuffer,
((dwBufferSize+INIBUF_GROW)*sizeof(TCHAR)),
LMEM_MOVEABLE))
{
lpBuffer = lpNew;
dwBufferSize += INIBUF_GROW;
}
else
{
LogFactoryInstallError(TEXT("FACTORY:: Failed to Re-allocate a buffer for reading the WINBOM file"));
bRet = FALSE;
goto Clean1;
}
dwResult = GetPrivateProfileString(lpszSectionName,
NULL, // Get all keys
TEXT(""),
lpBuffer,
dwBufferSize,
lpszIniFileName);
}
// Walk the list, building the DeviceIDList
for(lpKeys = lpBuffer; *lpKeys; lpKeys+=dwKeyLen)
{
dwKeyLen = lstrlen(lpKeys)+1;
// Copy the HW ID
// NTRAID#NTBUG9-551266-2002/02/26-acosma - Buffer overrun possibility.
//
lstrcpy(lpDevIDList[*lpdwNumDeviceIDs].szHardwareID, lpKeys);
// Get the INF name
GetPrivateProfileString(lpszSectionName,
lpKeys,
TEXT(""),
szINFFileName,
MAX_PATH,
lpszIniFileName);
ExpandEnvironmentStrings(szINFFileName, lpDevIDList[*lpdwNumDeviceIDs].szINFFileName, MAX_PATH);
++(*lpdwNumDeviceIDs);
// See if the device ID buffer needs to be reallocated
if (*lpdwNumDeviceIDs == dwSizeDevIDList)
{
if(lpNew = LocalReAlloc(*lplpDeviceIDList,
((dwSizeDevIDList + DEVID_ARRAY_GROW)*sizeof(DEVIDLIST)),
LMEM_MOVEABLE))
{
*lplpDeviceIDList = (LPDEVIDLIST)lpNew;
lpDevIDList = *lplpDeviceIDList;
dwSizeDevIDList += DEVID_ARRAY_GROW;
}
else
{
LogFactoryInstallError(TEXT("FACTORY:: Failed to Re-allocate a buffer for reading the WINBOM file"));
bRet = FALSE;
goto Clean1;
}
}
}
}
}
else
{
// See if there was an error, or the section just does not exist
if (GetLastError() != 0)
{
bRet = FALSE;
}
}
Clean1:
if (lpBuffer)
{
LocalFree(lpBuffer);
}
return bRet;
}