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.
 
 
 
 
 
 

1126 lines
40 KiB

//
// DEVNODE.C
//
#include "sigverif.h"
#include <initguid.h>
#include <devguid.h>
//
// Given the full path to a driver, add it to the file list.
//
LPFILENODE
AddDriverFileToList(
LPTSTR lpDirName,
LPTSTR lpFullPathName
)
{
DWORD Err = ERROR_SUCCESS;
LPFILENODE lpFileNode = NULL;
TCHAR szDirName[MAX_PATH];
TCHAR szFileName[MAX_PATH];
LPTSTR lpFilePart;
*szDirName = 0;
*szFileName = 0;
//
// If no directory is passed in, try to get the full path
//
if (!lpDirName || !*lpDirName) {
if (GetFullPathName(lpFullPathName, cA(szDirName), szDirName, &lpFilePart)) {
if (lpFilePart && *lpFilePart) {
if (SUCCEEDED(StringCchCopy(szFileName, cA(szFileName), lpFilePart))) {
*lpFilePart = 0;
if (lstrlen(szDirName) > 3) {
*(lpFilePart - 1) = 0;
}
} else {
*szFileName = 0;
}
}
} else {
*szDirName = 0;
}
} else {
//
// Use the directory and filename that was passed in to us
// Expand out lpDirName in case there are any ".." entries
//
if (!GetFullPathName(lpDirName, cA(szDirName), szDirName, NULL)) {
//
// If we can't get the full path, then just use the one
// that was passed in. This could happen if the directory
// is missing for instance.
//
if (FAILED(StringCchCopy(szDirName, cA(szDirName), lpDirName))) {
//
// If we can't fit the directory name into our buffer then
// clear szDirName so this node won't be added to the list.
//
*szDirName = 0;
}
}
if (FAILED(StringCchCopy(szFileName, cA(szFileName), lpFullPathName))) {
//
// If we can't fit the file name into our buffer then
// clear szFileName so this node won't be added to the list.
//
*szFileName = 0;
}
}
if (*szDirName && *szFileName && !IsFileAlreadyInList(szDirName, szFileName)) {
//
// Create a filenode, based on the directory and filename
//
lpFileNode = CreateFileNode(szDirName, szFileName);
if (lpFileNode) {
InsertFileNodeIntoList(lpFileNode);
//
// Increment the total number of files we've found that meet the
// search criteria.
//
g_App.dwFiles++;
} else {
Err = GetLastError();
}
}
SetLastError(Err);
return lpFileNode;
}
BOOL
GetFullPathFromImagePath(
LPCTSTR ImagePath,
LPTSTR FullPath,
UINT FullPathLength
)
{
TCHAR OriginalCurrentDirectory[MAX_PATH];
LPTSTR pRelativeString;
LPTSTR lpFilePart;
if (!ImagePath || (ImagePath[0] == TEXT('\0'))) {
return FALSE;
}
//
// First check if the ImagePath happens to be a valid full path.
//
if (GetFileAttributes(ImagePath) != 0xFFFFFFFF) {
GetFullPathName(ImagePath, FullPathLength, FullPath, &lpFilePart);
return TRUE;
}
pRelativeString = (LPTSTR)ImagePath;
//
// If the ImagePath starts with "\SystemRoot" or "%SystemRoot%" then
// remove those values.
//
if (StrCmpNI(ImagePath, TEXT("\\SystemRoot\\"), lstrlen(TEXT("\\SystemRoot\\"))) == 0) {
pRelativeString += lstrlen(TEXT("\\SystemRoot\\"));
} else if (StrCmpNI(ImagePath, TEXT("%SystemRoot%\\"), lstrlen(TEXT("%SystemRoot%\\"))) == 0) {
pRelativeString += lstrlen(TEXT("%SystemRoot%\\"));
}
//
// At this point pRelativeString should point to the image path relative to
// the windows directory.
//
if (!GetSystemWindowsDirectory(FullPath, FullPathLength)) {
return FALSE;
}
if (!GetCurrentDirectory(cA(OriginalCurrentDirectory), OriginalCurrentDirectory)) {
OriginalCurrentDirectory[0] = TEXT('\0');
}
if (!SetCurrentDirectory(FullPath)) {
return FALSE;
}
GetFullPathName(pRelativeString, FullPathLength, FullPath, &lpFilePart);
if (OriginalCurrentDirectory[0] != TEXT('\0')) {
SetCurrentDirectory(OriginalCurrentDirectory);
}
return TRUE;
}
DWORD
CreateFromService(
SC_HANDLE hscManager,
PCTSTR ServiceName
)
{
DWORD Err = ERROR_SUCCESS;
SC_HANDLE hscService = NULL;
DWORD BytesRequired, Size;
TCHAR FullPath[MAX_PATH];
LPQUERY_SERVICE_CONFIG pqsc;
PBYTE BufferPtr = NULL;
if (hscManager == NULL) {
//
// This should never happen.
//
goto clean0;
}
if (!ServiceName ||
(ServiceName[0] == TEXT('\0'))) {
//
// This should also never happen.
//
goto clean0;
}
hscService = OpenService(hscManager, ServiceName, GENERIC_READ);
if (NULL == hscService) {
//
// This service does not exist. We won't return an error in this case
// since if the service doesn't exist then the driver won't get
// loaded.
//
goto clean0;
}
//
// First, probe for buffer size
//
if (!QueryServiceConfig(hscService, NULL, 0, &BytesRequired) &&
ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
BufferPtr = MALLOC(BytesRequired);
if (!BufferPtr) {
Err = ERROR_NOT_ENOUGH_MEMORY;
goto clean0;
}
pqsc = (LPQUERY_SERVICE_CONFIG)(PBYTE)BufferPtr;
if (QueryServiceConfig(hscService, pqsc, BytesRequired, &Size) &&
pqsc->lpBinaryPathName &&
(TEXT('\0') != pqsc->lpBinaryPathName[0])) {
//
// Make sure we have a valid full path.
//
if (GetFullPathFromImagePath(pqsc->lpBinaryPathName,
FullPath,
cA(FullPath))) {
AddDriverFileToList(NULL, FullPath);
}
}
FREE(BufferPtr);
}
clean0:
if (hscService) {
CloseServiceHandle(hscService);
hscService = NULL;
}
if (BufferPtr) {
FREE(BufferPtr);
}
return Err;
}
UINT
ScanQueueCallback(
PVOID Context,
UINT Notification,
UINT_PTR Param1,
UINT_PTR Param2
)
{
LPFILENODE lpFileNode;
TCHAR szBuffer[MAX_PATH];
LPTSTR lpFilePart;
ULONG BufCbSize;
HRESULT hr;
UNREFERENCED_PARAMETER(Param2);
if ((Notification == SPFILENOTIFY_QUEUESCAN_SIGNERINFO) &&
Param1) {
//
// Special case for printers:
// After setupapi copies files from the file queue into their destination
// location, the printer class installer moves some of these files into
// other 'special' locations. This can lead to the callback Win32Error
// returning ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND since the file
// is not present in the location where setupapi put it. So, we will
// catch this case for printers and not add the file to our list of
// files to scan. These 'special' printer files will get added later
// when we call the spooler APIs.
// Also note that we can't just skip getting the list of files for printers
// altogether since the printer class installer only moves some of the
// files that setupapi copies and not all of them.
//
if (Context &&
(IsEqualGUID((LPGUID)Context, &GUID_DEVCLASS_PRINTER)) &&
((((PFILEPATHS_SIGNERINFO)Param1)->Win32Error == ERROR_FILE_NOT_FOUND) ||
(((PFILEPATHS_SIGNERINFO)Param1)->Win32Error == ERROR_PATH_NOT_FOUND))) {
//
// Assume this was a file moved by the printer class installer. Don't
// add it to the list of files to be scanned at this time.
//
return NO_ERROR;
}
lpFileNode = AddDriverFileToList(NULL,
(LPTSTR)((PFILEPATHS_SIGNERINFO)Param1)->Target);
//
// Fill in some information into the FILENODE structure since we already
// scanned the file.
//
if (lpFileNode) {
lpFileNode->bScanned = TRUE;
lpFileNode->bSigned = (((PFILEPATHS_SIGNERINFO)Param1)->Win32Error == NO_ERROR);
if (lpFileNode->bSigned) {
if (((PFILEPATHS_SIGNERINFO)Param1)->CatalogFile) {
GetFullPathName(((PFILEPATHS_SIGNERINFO)Param1)->CatalogFile, cA(szBuffer), szBuffer, &lpFilePart);
BufCbSize = (lstrlen(lpFilePart) + 1) * sizeof(TCHAR);
lpFileNode->lpCatalog = MALLOC(BufCbSize);
if (lpFileNode->lpCatalog) {
hr = StringCbCopy(lpFileNode->lpCatalog, BufCbSize, lpFilePart);
if (FAILED(hr) && (hr != STRSAFE_E_INSUFFICIENT_BUFFER)) {
//
// If we fail for some reason other than insufficient
// buffer, then free the string and set the pointer
// to NULL, since the string is undefined.
//
FREE(lpFileNode->lpCatalog);
lpFileNode->lpCatalog = NULL;
}
}
}
if (((PFILEPATHS_SIGNERINFO)Param1)->DigitalSigner) {
BufCbSize = (lstrlen(((PFILEPATHS_SIGNERINFO)Param1)->DigitalSigner) + 1) * sizeof(TCHAR);
lpFileNode->lpSignedBy = MALLOC(BufCbSize);
if (lpFileNode->lpSignedBy) {
hr = StringCbCopy(lpFileNode->lpSignedBy, BufCbSize, ((PFILEPATHS_SIGNERINFO)Param1)->DigitalSigner);
if (FAILED(hr) && (hr != STRSAFE_E_INSUFFICIENT_BUFFER)) {
//
// If we fail for some reason other than insufficient
// buffer, then free the string and set the pointer
// to NULL, since the string is undefined.
//
FREE(lpFileNode->lpSignedBy);
lpFileNode->lpSignedBy = NULL;
}
}
}
if (((PFILEPATHS_SIGNERINFO)Param1)->Version) {
BufCbSize = (lstrlen(((PFILEPATHS_SIGNERINFO)Param1)->Version) + 1) * sizeof(TCHAR);
lpFileNode->lpVersion = MALLOC(BufCbSize);
if (lpFileNode->lpVersion) {
hr = StringCbCopy(lpFileNode->lpVersion, BufCbSize, ((PFILEPATHS_SIGNERINFO)Param1)->Version);
if (FAILED(hr) && (hr != STRSAFE_E_INSUFFICIENT_BUFFER)) {
//
// If we fail for some reason other than insufficient
// buffer, then free the string and set the pointer
// to NULL, since the string is undefined.
//
FREE(lpFileNode->lpVersion);
lpFileNode->lpVersion = NULL;
}
}
}
} else {
//
// Get the icon (if the file isn't signed) so we can display it in the listview faster.
//
MyGetFileInfo(lpFileNode);
}
}
}
return NO_ERROR;
}
void
AddClassInstallerToList(
LPCTSTR ClassInstallerString
)
{
DWORD BufferSize;
TCHAR ModulePath[MAX_PATH];
TCHAR TempBuffer[MAX_PATH];
PTSTR StringPtr;
if ((ClassInstallerString == NULL) ||
(ClassInstallerString[0] == TEXT('\0'))) {
return;
}
if (FAILED(StringCchCopy(TempBuffer, cA(TempBuffer), ClassInstallerString))) {
return;
}
//
// Class/Co-installers are always based under the %windir%\system32
// directory.
//
if (GetSystemDirectory(ModulePath, cA(ModulePath)) == 0) {
return;
}
//
// Find the beginning of the entry point name, if present.
//
BufferSize = (lstrlen(TempBuffer) + 1) * sizeof(TCHAR);
for(StringPtr = TempBuffer + ((BufferSize / sizeof(TCHAR)) - 2);
StringPtr >= TempBuffer;
StringPtr--) {
if(*StringPtr == TEXT(',')) {
*(StringPtr++) = TEXT('\0');
break;
}
//
// If we hit a double-quote mark, then set the character pointer
// to the beginning of the string so we'll terminate the search.
//
if(*StringPtr == TEXT('\"')) {
StringPtr = TempBuffer;
}
}
if (pSetupConcatenatePaths(ModulePath, TempBuffer, MAX_PATH, NULL)) {
AddDriverFileToList(NULL, ModulePath);
}
}
DWORD
BuildDriverFileList(
void
)
{
DWORD Err = ERROR_SUCCESS;
HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
SP_DEVINFO_DATA DeviceInfoData;
SP_DRVINFO_DATA DriverInfoData;
SP_DEVINSTALL_PARAMS DeviceInstallParams;
DWORD DeviceMemberIndex;
HSPFILEQ hFileQueue;
DWORD ScanResult;
DWORD Status, Problem;
SC_HANDLE hscManager = NULL;
TCHAR Buffer[MAX_PATH];
ULONG BufferSize;
DWORD dwType;
HKEY hKey = INVALID_HANDLE_VALUE, hKeyClassCoInstallers = INVALID_HANDLE_VALUE;
PTSTR pItemList = NULL, pSingleItem;
LPGUID ClassGuidList = NULL;
DWORD i, NumberClassGuids, CurrentClassGuid;
TCHAR GuidString[MAX_GUID_STRING_LEN];
//
// Build up a list of all the devices in the system.
//
hDeviceInfo = SetupDiGetClassDevs(NULL,
NULL,
NULL,
DIGCF_ALLCLASSES
);
if (hDeviceInfo == INVALID_HANDLE_VALUE) {
Err = GetLastError();
goto clean0;
}
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
DeviceMemberIndex = 0;
//
// Enumerate through the list of devices and get a list of all
// the files they copy, if they are signed or not, and which catalog
// signed them.
//
while (SetupDiEnumDeviceInfo(hDeviceInfo,
DeviceMemberIndex++,
&DeviceInfoData
) &&
!g_App.bStopScan) {
//
// We will only build up a driver list for swenum phantoms. All other
// phantoms will be skipped.
//
if (CM_Get_DevNode_Status(&Status,
&Problem,
DeviceInfoData.DevInst,
0) == CR_NO_SUCH_DEVINST) {
//
// This device is a phantom, if it is not a swenum device, then
// skip it.
//
if (!SetupDiGetDeviceRegistryProperty(hDeviceInfo,
&DeviceInfoData,
SPDRP_ENUMERATOR_NAME,
NULL,
(PBYTE)Buffer,
sizeof(Buffer),
NULL) ||
(_wcsicmp(Buffer, TEXT("SW")) != 0)) {
//
// Either we couldn't get the enumerator name, or it is not
// SW.
//
continue;
}
}
DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
//
// Before we call SetupDiBuildDriverInfoList to build up a list of drivers
// for this device we first need to set the DI_FLAGSEX_INSTALLEDDRIVER flag
// (which tells the API to only include the currently installed driver in
// the list) and the DI_FLAGSEX_ALLOWEXCLUDEDRVS (allow ExcludeFromSelect
// devices in the list).
//
if (SetupDiGetDeviceInstallParams(hDeviceInfo,
&DeviceInfoData,
&DeviceInstallParams
)) {
DeviceInstallParams.FlagsEx = (DI_FLAGSEX_INSTALLEDDRIVER |
DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
if (SetupDiSetDeviceInstallParams(hDeviceInfo,
&DeviceInfoData,
&DeviceInstallParams
) &&
SetupDiBuildDriverInfoList(hDeviceInfo,
&DeviceInfoData,
SPDIT_CLASSDRIVER
)) {
//
// Now we will get the one driver node that is in the list that
// was just built and make it the selected driver node.
//
DriverInfoData.cbSize = sizeof(DriverInfoData);
if (SetupDiEnumDriverInfo(hDeviceInfo,
&DeviceInfoData,
SPDIT_CLASSDRIVER,
0,
&DriverInfoData
) &&
SetupDiSetSelectedDriver(hDeviceInfo,
&DeviceInfoData,
&DriverInfoData
)) {
hFileQueue = SetupOpenFileQueue();
if (hFileQueue != INVALID_HANDLE_VALUE) {
//
// Set the FileQueue parameter to the file queue we just
// created and set the DI_NOVCP flag.
//
// The call SetupDiCallClassInstaller with DIF_INSTALLDEVICEFILES
// to build up a queue of all the files that are copied for
// this driver node.
//
DeviceInstallParams.FileQueue = hFileQueue;
DeviceInstallParams.Flags |= DI_NOVCP;
if (SetupDiSetDeviceInstallParams(hDeviceInfo,
&DeviceInfoData,
&DeviceInstallParams
) &&
SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
hDeviceInfo,
&DeviceInfoData
)) {
//
// Scan the file queue and have it call our callback
// function for each file in the queue.
//
SetupScanFileQueue(hFileQueue,
SPQ_SCAN_USE_CALLBACK_SIGNERINFO,
NULL,
ScanQueueCallback,
(PVOID)&(DeviceInfoData.ClassGuid),
&ScanResult
);
//
// Dereference the file queue so we can close it.
//
DeviceInstallParams.FileQueue = NULL;
DeviceInstallParams.Flags &= ~DI_NOVCP;
SetupDiSetDeviceInstallParams(hDeviceInfo,
&DeviceInfoData,
&DeviceInstallParams
);
}
SetupCloseFileQueue(hFileQueue);
}
}
SetupDiDestroyDriverInfoList(hDeviceInfo,
&DeviceInfoData,
SPDIT_CLASSDRIVER
);
}
}
}
//
// Enumerate through the list of devices and add any function, device
// upper/lower filters, and class upper/lower filter drivers to the list
// that aren't already in the list.
// We are doing this after we get all the files copied by the INF, because
// these files can only be validated globally, where the INF copied files
// can be validated using the catalog associated with their package.
//
hscManager = OpenSCManager(NULL, NULL, GENERIC_READ);
if (hscManager) {
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
DeviceMemberIndex = 0;
while (SetupDiEnumDeviceInfo(hDeviceInfo,
DeviceMemberIndex++,
&DeviceInfoData
) &&
!g_App.bStopScan) {
//
// Only look at SWENUM phantoms
//
if (CM_Get_DevNode_Status(&Status,
&Problem,
DeviceInfoData.DevInst,
0) == CR_NO_SUCH_DEVINST) {
//
// This device is a phantom, if it is not a swenum device, then
// skip it.
//
if (!SetupDiGetDeviceRegistryProperty(hDeviceInfo,
&DeviceInfoData,
SPDRP_ENUMERATOR_NAME,
NULL,
(PBYTE)Buffer,
sizeof(Buffer),
NULL) ||
(_wcsicmp(Buffer, TEXT("SW")) != 0)) {
//
// Either we couldn't get the enumerator name, or it is not
// SW.
//
continue;
}
}
if (g_App.bStopScan) {
continue;
}
//
// Function driver.
//
if (SetupDiGetDeviceRegistryProperty(hDeviceInfo,
&DeviceInfoData,
SPDRP_SERVICE,
NULL,
(PBYTE)Buffer,
sizeof(Buffer),
NULL)) {
CreateFromService(hscManager, Buffer);
}
if (g_App.bStopScan) {
continue;
}
//
// Upper and Lower device filters
//
for (i=0; i<2; i++) {
BufferSize = 0;
SetupDiGetDeviceRegistryProperty(hDeviceInfo,
&DeviceInfoData,
i ? SPDRP_LOWERFILTERS : SPDRP_UPPERFILTERS,
NULL,
NULL,
BufferSize,
&BufferSize);
if (BufferSize > 0) {
pItemList = MALLOC(BufferSize + (2 * sizeof(TCHAR)));
if (!pItemList) {
Err = ERROR_NOT_ENOUGH_MEMORY;
goto clean0;
}
if (SetupDiGetDeviceRegistryProperty(hDeviceInfo,
&DeviceInfoData,
i ? SPDRP_LOWERFILTERS : SPDRP_UPPERFILTERS,
NULL,
(PBYTE)pItemList,
BufferSize,
&BufferSize)) {
for (pSingleItem=pItemList;
*pSingleItem;
pSingleItem += (lstrlen(pSingleItem) + 1)) {
CreateFromService(hscManager, pSingleItem);
}
}
FREE(pItemList);
}
}
if (g_App.bStopScan) {
continue;
}
//
// Device co-installers.
//
hKey = SetupDiOpenDevRegKey(hDeviceInfo,
&DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_READ);
if (hKey != INVALID_HANDLE_VALUE) {
BufferSize = 0;
RegQueryValueEx(hKey,
REGSTR_VAL_COINSTALLERS_32,
NULL,
&dwType,
NULL,
&BufferSize);
if (BufferSize > 0) {
pItemList = MALLOC(BufferSize + (2 * sizeof(TCHAR)));
if (!pItemList) {
Err = ERROR_NOT_ENOUGH_MEMORY;
goto clean0;
}
dwType = REG_MULTI_SZ;
if (RegQueryValueEx(hKey,
REGSTR_VAL_COINSTALLERS_32,
NULL,
&dwType,
(PBYTE)pItemList,
&BufferSize) == ERROR_SUCCESS) {
for (pSingleItem=pItemList;
*pSingleItem;
pSingleItem += (lstrlen(pSingleItem) + 1)) {
AddClassInstallerToList(pSingleItem);
}
}
FREE(pItemList);
}
RegCloseKey(hKey);
hKey = INVALID_HANDLE_VALUE;
}
}
//
// Enumerate through the classes so we can get the class upper and
// lower filters and the class installers.
//
NumberClassGuids = 0;
SetupDiBuildClassInfoList(0, NULL, 0, &NumberClassGuids);
if (NumberClassGuids > 0) {
ClassGuidList = MALLOC(NumberClassGuids * sizeof(GUID));
if (!ClassGuidList) {
Err = ERROR_NOT_ENOUGH_MEMORY;
goto clean0;
}
if (SetupDiBuildClassInfoList(0, ClassGuidList, NumberClassGuids, &NumberClassGuids)) {
//
// Open the class co-installer key since we will go through that
// list while we have the class guids handy.
//
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
REGSTR_PATH_CODEVICEINSTALLERS,
0,
KEY_READ,
&hKeyClassCoInstallers) != ERROR_SUCCESS) {
hKeyClassCoInstallers = INVALID_HANDLE_VALUE;
}
for (CurrentClassGuid=0; CurrentClassGuid<NumberClassGuids; CurrentClassGuid++) {
//
// Open the class key.
//
hKey = SetupDiOpenClassRegKey(&(ClassGuidList[CurrentClassGuid]),
KEY_READ);
if (hKey != INVALID_HANDLE_VALUE) {
//
// Upper and Lower class filters
//
for (i=0; i<2; i++) {
BufferSize = 0;
RegQueryValueEx(hKey,
i ? REGSTR_VAL_LOWERFILTERS : REGSTR_VAL_UPPERFILTERS,
NULL,
&dwType,
NULL,
&BufferSize);
if (BufferSize > 0) {
pItemList = MALLOC(BufferSize + (2 * sizeof(TCHAR)));
if (!pItemList) {
Err = ERROR_NOT_ENOUGH_MEMORY;
goto clean0;
}
dwType = REG_MULTI_SZ;
if (RegQueryValueEx(hKey,
i ? REGSTR_VAL_LOWERFILTERS : REGSTR_VAL_UPPERFILTERS,
NULL,
&dwType,
(PBYTE)pItemList,
&BufferSize) == ERROR_SUCCESS) {
for (pSingleItem=pItemList;
*pSingleItem;
pSingleItem += (lstrlen(pSingleItem) + 1)) {
CreateFromService(hscManager, pSingleItem);
}
}
FREE(pItemList);
}
}
//
// Class installer
//
dwType = REG_SZ;
BufferSize = sizeof(Buffer);
if (RegQueryValueEx(hKey,
REGSTR_VAL_INSTALLER_32,
NULL,
&dwType,
(PBYTE)Buffer,
&BufferSize) == ERROR_SUCCESS) {
AddClassInstallerToList(Buffer);
}
RegCloseKey(hKey);
hKey = INVALID_HANDLE_VALUE;
}
//
// Class co-installers.
//
if (hKeyClassCoInstallers != INVALID_HANDLE_VALUE) {
if (pSetupStringFromGuid(&(ClassGuidList[CurrentClassGuid]),
GuidString,
cA(GuidString)) == ERROR_SUCCESS) {
BufferSize = 0;
RegQueryValueEx(hKeyClassCoInstallers,
GuidString,
NULL,
&dwType,
NULL,
&BufferSize);
if (BufferSize > 0) {
pItemList = MALLOC(BufferSize + (2 * sizeof(TCHAR)));
if (!pItemList) {
Err = ERROR_NOT_ENOUGH_MEMORY;
goto clean0;
}
dwType = REG_MULTI_SZ;
if (RegQueryValueEx(hKeyClassCoInstallers,
GuidString,
NULL,
&dwType,
(PBYTE)pItemList,
&BufferSize) == ERROR_SUCCESS) {
for (pSingleItem=pItemList;
*pSingleItem;
pSingleItem += (lstrlen(pSingleItem) + 1)) {
AddClassInstallerToList(pSingleItem);
}
}
FREE(pItemList);
}
}
}
}
}
if (hKeyClassCoInstallers != INVALID_HANDLE_VALUE) {
RegCloseKey(hKeyClassCoInstallers);
hKeyClassCoInstallers = INVALID_HANDLE_VALUE;
}
FREE(ClassGuidList);
}
CloseServiceHandle(hscManager);
}
clean0:
if (hscManager) {
CloseServiceHandle(hscManager);
}
if (pItemList) {
FREE(pItemList);
}
if (ClassGuidList) {
FREE(ClassGuidList);
}
if (hDeviceInfo != INVALID_HANDLE_VALUE) {
SetupDiDestroyDeviceInfoList(hDeviceInfo);
}
if (hKeyClassCoInstallers != INVALID_HANDLE_VALUE) {
RegCloseKey(hKeyClassCoInstallers);
hKeyClassCoInstallers = INVALID_HANDLE_VALUE;
}
if (hKey != INVALID_HANDLE_VALUE) {
RegCloseKey(hKey);
hKey = INVALID_HANDLE_VALUE;
}
return Err;
}
DWORD
BuildPrinterFileList(
void
)
{
DWORD Err = ERROR_SUCCESS;
BOOL bRet;
DWORD dwBytesNeeded = 0;
DWORD dwDrivers = 0;
LPBYTE lpBuffer = NULL, lpTemp = NULL;
LPTSTR lpFileName;
DRIVER_INFO_3 DriverInfo;
PDRIVER_INFO_3 lpDriverInfo;
TCHAR szBuffer[MAX_PATH];
LPFILENODE lpFileNode = NULL;
ZeroMemory(&DriverInfo, sizeof(DRIVER_INFO_3));
bRet = EnumPrinterDrivers( NULL,
SIGVERIF_PRINTER_ENV,
3,
(LPBYTE) &DriverInfo,
sizeof(DRIVER_INFO_3),
&dwBytesNeeded,
&dwDrivers);
if (!bRet && dwBytesNeeded > 0) {
lpBuffer = MALLOC(dwBytesNeeded);
//
// If we can't get any memory then just bail out of this function
//
if (!lpBuffer) {
Err = ERROR_NOT_ENOUGH_MEMORY;
goto clean0;
}
bRet = EnumPrinterDrivers( NULL,
SIGVERIF_PRINTER_ENV,
3,
(LPBYTE) lpBuffer,
dwBytesNeeded,
&dwBytesNeeded,
&dwDrivers);
}
if (dwDrivers > 0) {
//
// By default, go into the System directory, since Win9x doesn't give full paths to drivers.
//
GetSystemDirectory(szBuffer, cA(szBuffer));
SetCurrentDirectory(szBuffer);
for (lpTemp = lpBuffer; dwDrivers > 0; dwDrivers--) {
lpDriverInfo = (PDRIVER_INFO_3) lpTemp;
if (lpDriverInfo->pName) {
if (lpDriverInfo->pDriverPath && *lpDriverInfo->pDriverPath) {
lpFileNode = AddDriverFileToList(NULL, lpDriverInfo->pDriverPath);
if (lpFileNode) {
lpFileNode->bValidateAgainstAnyOs = TRUE;
}
}
if (lpDriverInfo->pDataFile && *lpDriverInfo->pDataFile) {
lpFileNode = AddDriverFileToList(NULL, lpDriverInfo->pDataFile);
if (lpFileNode) {
lpFileNode->bValidateAgainstAnyOs = TRUE;
}
}
if (lpDriverInfo->pConfigFile && *lpDriverInfo->pConfigFile) {
lpFileNode = AddDriverFileToList(NULL, lpDriverInfo->pConfigFile);
if (lpFileNode) {
lpFileNode->bValidateAgainstAnyOs = TRUE;
}
}
if (lpDriverInfo->pHelpFile && *lpDriverInfo->pHelpFile) {
lpFileNode = AddDriverFileToList(NULL, lpDriverInfo->pHelpFile);
if (lpFileNode) {
lpFileNode->bValidateAgainstAnyOs = TRUE;
}
}
lpFileName = lpDriverInfo->pDependentFiles;
while (lpFileName && *lpFileName) {
lpFileNode = AddDriverFileToList(NULL, lpFileName);
if (lpFileNode) {
lpFileNode->bValidateAgainstAnyOs = TRUE;
}
for (;*lpFileName;lpFileName++);
lpFileName++;
}
}
lpTemp += sizeof(DRIVER_INFO_3);
}
}
clean0:
if (lpBuffer) {
FREE(lpBuffer);
}
return Err;
}
DWORD
BuildCoreFileList(
void
)
{
DWORD Err = ERROR_SUCCESS;
PROTECTED_FILE_DATA pfd;
pfd.FileNumber = 0;
while (SfcGetNextProtectedFile(NULL, &pfd)) {
if (g_App.bStopScan) {
Err = ERROR_CANCELLED;
break;
}
AddDriverFileToList(NULL, pfd.FileName);
}
//
// See if SfcGetNextProtectedFile failed from some reason other than
// ERROR_NO_MORE_FILES.
//
if ((Err == ERROR_SUCCESS) &&
(GetLastError() != ERROR_NO_MORE_FILES)) {
//
// SfcGetNextProtectedFile failed before we reached then end of the
// list of protected file list. This means we won't scan all the
// protected files, so we should fail up front!
//
Err = GetLastError();
}
return Err;
}