// // DEVNODE.C // #include "sigverif.h" #include #include // // 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 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; }