windows-nt/Source/XPSP1/NT/windows/winstate/v1/scanstate/scanfiles.cxx

1188 lines
33 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1998 - 1998.
//
// File: scanfiles.cxx
//
// Contents: User file migration code
//
// Classes:
//
// Functions:
//
// History: 28-Sep-99 PhilipLa Created
//
//----------------------------------------------------------------------------
#include "scanhead.cxx"
#pragma hdrstop
#include <common.hxx>
#include <filelist.hxx>
#include <section.hxx>
#include <special.hxx>
#include <scanstate.hxx>
#include <bothchar.hxx>
#include <fileutil.cxx>
CSection *g_pcsSectionList = NULL;
CRuleList g_crlExcludeWildcards;
CRuleList g_crlIncludeWildcards;
CSpecialDirectory g_csd;
CSysFileList g_sfl;
DWORD ProcessSysFiles(HINF hi, const TCHAR *ptsName);
DWORD InitializeFiles()
{
DWORD dwErr;
dwErr = g_csd.Init();
if (dwErr)
{
return dwErr;
}
if (CopyFiles)
{
dwErr = ProcessSysFiles(InputInf, SYSFILES_LABEL);
if (dwErr != 0)
return dwErr;
}
return ERROR_SUCCESS;
}
void CleanupFiles(void)
{
FreeSectionList(g_pcsSectionList);
g_pcsSectionList = NULL;
}
//---------------------------------------------------------------
DWORD ComputeTemp()
{
return ERROR_SUCCESS;
}
//---------------------------------------------------------------
void EraseTemp()
{
}
//---------------------------------------------------------------
DWORD PickUpThisFile( char *file, char * dest)
{
DWORD dwErr;
DWORD dwIndex;
if ((file == NULL) ||
(file[0] == 0))
{
//Wacky NULL strings must not be added as rules.
//Ignore them and return success.
return ERROR_SUCCESS;
}
if (Verbose)
Win32Printf(LogFile,
"Copy %s to the destination machine.\r\n",
file );
TCHAR *ptsFile, *ptsDest;
TCHAR tsFileName[MAX_PATH + 1];
TCHAR tsTemp[MAX_PATH + 1];
#ifdef _UNICODE
TCHAR tsDest[MAX_PATH + 1];
if (!(MultiByteToWideChar(AreFileAPIsAnsi() ? CP_ACP : CP_OEMCP,
MB_ERR_INVALID_CHARS,
file,
-1,
tsFileName
MAX_PATH + 1)))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_INVALID_PARAMETER);
if (Verbose)
Win32Printf(STDERR,
"Couldn't convert output path %s to Unicode.\r\n",
file);
return dwErr;
}
if (dest &&
(!(MultiByteToWideChar(AreFileAPIsAnsi() ? CP_ACP : CP_OEMCP,
MB_ERR_INVALID_CHARS,
dest,
-1,
tsDest,
MAX_PATH + 1))))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_INVALID_PARAMETER);
if (Verbose)
Win32Printf(STDERR,
"Couldn't convert output path %s to Unicode.\r\n",
dest);
return dwErr;
}
ptsFile = tsFileName;
ptsDest = tsDest;
#else
ptsFile = file;
ptsDest = dest;
#endif //_UNICODE
if (_tcslen(ptsFile) > MAX_PATH)
{
if (DebugOutput)
{
Win32Printf(LogFile, "Error: ptsFile too long %s\r\n", ptsFile);
}
return ERROR_FILENAME_EXCED_RANGE;
}
_tcscpy(tsTemp, ptsFile);
dwErr = g_csd.ExpandMacro(tsTemp, tsFileName, &ptsFile, TRUE);
if (dwErr)
return dwErr;
CRuleList *prlDest;
dwErr = g_crlIncludeWildcards.SetName(ptsFile, &prlDest);
if (!dwErr && ptsDest)
dwErr = prlDest->SetDestination(ptsDest);
//Remove it from the system files list if it's in there.
g_sfl.RemoveName(ptsFile);
return dwErr;
}
DWORD CopyAFile(const TCHAR *ptsSourcePath, const TCHAR *ptsName)
{
BOOL fPath = FALSE;
DWORD dwErr = ERROR_SUCCESS;
DWORD dwLen;
TCHAR ptsMigrationPath[MAX_PATH + 1];
TCHAR ptsPath[MAX_PATH + 1];
TCHAR ptsSourceFullPath[MAX_PATH + 1];
// If the source filename is too long, skip it
if ( (_tcslen(ptsName) + _tcslen(ptsSourcePath) + 1) > MAX_PATH )
{
Win32PrintfResource(LogFile,
IDS_FILE_COPYERROR,
ptsName);
if (Verbose)
Win32Printf(STDERR,
"Could Not Copy Too Long Source Filename: %s\\%s\r\n",
ptsSourcePath,
ptsName);
return ERROR_FILENAME_EXCED_RANGE;
}
_tcscpy(ptsSourceFullPath, ptsSourcePath);
_tcscat(ptsSourceFullPath, TEXT("\\"));
_tcscat(ptsSourceFullPath, ptsName);
#ifdef _UNICODE
if (!(dwLen = MultiByteToWideChar(AreFileAPIsAnsi() ? CP_ACP : CP_OEMCP,
MB_ERR_INVALID_CHARS,
MigrationPath,
-1,
ptsMigrationPath,
MAX_PATH + 1)))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_INVALID_PARAMETER);
if (Verbose)
Win32Printf(STDERR,
"Couldn't convert output path %s to Unicode.\r\n",
MigrationPath);
return dwErr;
}
#else
dwLen = _tcslen(MigrationPath);
if (dwLen > MAX_PATH)
{
if (DebugOutput)
{
Win32Printf(LogFile, "Error: MigrationPath too long %s\r\n", MigrationPath);
}
return ERROR_FILENAME_EXCED_RANGE;
}
_tcscpy(ptsMigrationPath, MigrationPath);
#endif
// If the destination path is too long, skip this file
if ( (dwLen + _tcslen(ptsSourcePath) + _tcslen(ptsName)+1) > MAX_PATH )
{
Win32PrintfResource(LogFile,
IDS_FILE_COPYERROR,
ptsName);
if (Verbose)
Win32Printf(STDERR,
"Could Not Copy To Too Long Destination Filename: %s\\%c%s\\%s\r\n",
ptsMigrationPath,
ptsSourcePath[0],
ptsSourcePath+2,
ptsName);
return ERROR_FILENAME_EXCED_RANGE;
}
_tcscpy(ptsPath, ptsMigrationPath);
ptsPath[dwLen++] = TEXT('\\');
//Copy drive letter
ptsPath[dwLen++] = ptsSourcePath[0];
//Skip the colon
_tcscpy(ptsPath + dwLen, ptsSourcePath + 2);
dwLen = dwLen + _tcslen(ptsSourcePath) - 2;
ptsPath[dwLen++] = TEXT('\\');
_tcscpy(ptsPath + dwLen, ptsName);
if (ReallyCopyFiles)
{
while (!CopyFile(ptsSourceFullPath,
ptsPath,
TRUE))
{
dwErr = GetLastError();
if (dwErr == ERROR_PATH_NOT_FOUND)
{
if (fPath)
{
//We already tried to create the path, so something
//else must be wrong. Punt-arooney.
break;
}
dwErr = ERROR_SUCCESS;
TCHAR *ptsPos;
DWORD dwPos;
//Try to create all the necessary directories
TCHAR ptsDirectory[MAX_PATH + 1];
// ptsPath is built inside this function and guarenteed to be less than MAX_PATH
_tcscpy(ptsDirectory, ptsPath);
dwPos = _tcslen(ptsMigrationPath) + 1;
//Create every directory along this path
while (ptsPos = _tcschr(ptsDirectory + dwPos, TEXT('\\')))
{
*ptsPos = TEXT(0);
//Create the directory
if (!CreateDirectory(ptsDirectory,
NULL))
{
dwErr = GetLastError();
if (dwErr != ERROR_ALREADY_EXISTS)
{
if (Verbose)
Win32Printf(STDERR,
"Error %lu trying to create "
"directory %s\r\n",
dwErr,
ptsDirectory);
break;
}
dwErr = ERROR_SUCCESS;
}
//Put the backslash back in
*ptsPos = TEXT('\\');
//Update dwLen
dwPos = ptsPos - ptsDirectory + 1;
}
if (dwErr)
break;
fPath = TRUE;
}
else if (dwErr == ERROR_ACCESS_DENIED)
{
// Ignore files that we don't have permission to copy anyway
Win32PrintfResource(LogFile,
IDS_ACCESS_DENIED,
ptsSourceFullPath);
dwErr = ERROR_SUCCESS;
break;
}
else
{
break;
}
}
}
if (dwErr)
{
Win32PrintfResource(LogFile,
IDS_FILE_COPYERROR,
ptsSourceFullPath);
if (Verbose)
Win32Printf(STDERR,
"Error %lu while copying from %s to %s\r\n",
dwErr,
ptsSourceFullPath,
ptsPath);
}
return dwErr;
}
const TCHAR * GetSpecialDirectoryName(const TCHAR *ptsPath)
{
TCHAR buf[MAX_PATH + 1];
if (_tcslen(ptsPath) > MAX_PATH)
{
if (DebugOutput)
{
Win32Printf(LogFile, "Error: ptsPath too long %s\r\n", ptsPath);
}
return NULL;
}
_tcscpy(buf, ptsPath);
DEBUG_ASSERT(buf[_tcslen(ptsPath) - 1] == TEXT('\\'));
buf[_tcslen(ptsPath) - 1] = 0;
for (ULONG i = 0; i < g_csd.GetDirectoryCount(); i++)
{
if (g_csd.GetDirectoryPath(i) &&
(_tcsicmp(buf, g_csd.GetDirectoryPath(i)) == 0))
{
return g_csd.GetDirectoryName(i);
}
}
return NULL;
}
BOOL ExcludeFile(const TCHAR *ptsRoot,
const TCHAR *ptsName,
const WIN32_FIND_DATA *pwfd,
CRuleList **pprlMatch,
DWORD *pdwMatchFit)
{
BOOL f;
TCHAR *ptsExt;
// This used to exclude HIDDEN and SYSTEM files,
// but it turns out we do want to migrate those
// if we have a matching rule. Note that system
// files will be excluded if they are listed in the
// system files section of the INF files.
if (pwfd->dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)
{
if (pprlMatch)
*pprlMatch = NULL;
//Infinite strength on this hit, we should never take these
//files even if we have a good include rule.
if (pdwMatchFit)
*pdwMatchFit = MAX_WEIGHT;
return TRUE;
}
f = g_crlExcludeWildcards.MatchAgainstRuleList(ptsRoot,
ptsName,
pprlMatch,
pdwMatchFit);
if (!f && !CopyFiles)
{
//User specified no file copy, so pretend there's a low
//priority rule that returned a hit. Any explicit include
//(which will only be coming from PickUpThisFile) will win.
if (pprlMatch)
*pprlMatch = NULL;
if (pdwMatchFit)
*pdwMatchFit = 1;
return TRUE;
}
return f;
}
BOOL IncludeFile(const TCHAR *ptsRoot,
const TCHAR *ptsName,
const WIN32_FIND_DATA *pwfd,
CRuleList **pprlMatch)
{
CRuleList *prlExclude = NULL;
CRuleList *prlInclude = NULL;
DWORD dwBestExcludeFit = 0;
DWORD dwBestIncludeFit = 0;
ExcludeFile(ptsRoot,
ptsName,
pwfd,
&prlExclude,
&dwBestExcludeFit);
g_crlIncludeWildcards.MatchAgainstRuleList(ptsRoot,
ptsName,
&prlInclude,
&dwBestIncludeFit);
if (DebugOutput)
Win32Printf(LogFile, "File %s%s rule weighting: \r\n Best exclude %lu = %s\r\n Best include %lu = %s\r\n",
ptsRoot,
(ptsName == NULL) ? TEXT("") : ptsName,
dwBestExcludeFit,
((prlExclude == NULL) ?
TEXT("NULL") :
prlExclude->GetFullName()),
dwBestIncludeFit,
((prlInclude == NULL) ?
TEXT("NULL") :
prlInclude->GetFullName()));
// Include the file when Include rating is stronger than Exclude rating, OR
// There is an Exclude and Include rule that both match this equally, OR
// No rules match this and we include by default, OR
// No rules match this and it's a directory
if ( (dwBestIncludeFit > dwBestExcludeFit) ||
( (dwBestIncludeFit == dwBestExcludeFit) &&
( (ExcludeByDefault == FALSE) ||
(dwBestIncludeFit > 0) ||
(pwfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))))
{
if (ptsName && g_sfl.LookupName(ptsName))
{
// If this file is listed as a system file in our rules,
// then always exclude it
if (pprlMatch)
*pprlMatch = NULL;
return FALSE;
}
//Include the file
if (pprlMatch)
*pprlMatch = prlInclude;
return TRUE;
}
else
{
if (pprlMatch)
*pprlMatch = prlExclude;
return FALSE;
}
}
BOOL PathPrefix(const TCHAR *ptsPath, const TCHAR *ptsInclude)
{
TCHAR ptsIncludePath[MAX_PATH + 1];
TCHAR ptsWildPath[MAX_PATH + 1];
if (_tcslen(ptsPath) + 2 > MAX_PATH)
{
if (DebugOutput)
{
Win32Printf(LogFile, "Error: ptsPath too long %s\r\n", ptsPath);
}
return FALSE;
}
_tcscpy(ptsWildPath, ptsPath);
_tcscat(ptsWildPath, TEXT("*\\"));
DeconstructFilename(ptsInclude,
ptsIncludePath,
NULL,
NULL);
if (ptsIncludePath[0])
{
BOOL fRet = IsPatternMatchFull(ptsWildPath, ptsIncludePath, NULL) ||
IsPatternMatchFull(ptsIncludePath, ptsPath, NULL);
return fRet;
}
return FALSE;
}
BOOL IncludeDirectory(const TCHAR *ptsPath, const WIN32_FIND_DATA *pwfd)
{
CRuleList *prl = g_crlIncludeWildcards.GetNextRule();
while (prl != NULL)
{
if (PathPrefix(ptsPath, prl->GetFullName()))
{
return TRUE;
}
prl = prl->GetNextRule();
}
return FALSE;
}
DWORD ProcessFileTree(TCHAR *ptsRoot,
CSection *pcsSection,
ULONG cRecursionLevel)
{
DWORD dwErr;
HANDLE hNext;
WIN32_FIND_DATA wfd;
TCHAR ptsStart[MAX_PATH];
const TCHAR *ptsSpecialName = GetSpecialDirectoryName(ptsRoot);
if ((cRecursionLevel < 2) || (ptsSpecialName != NULL))
{
pcsSection = new CSection;
if (pcsSection == NULL)
{
Win32PrintfResource(LogFile, IDS_NOT_ENOUGH_MEMORY);
return ERROR_OUTOFMEMORY;
}
if (g_pcsSectionList == NULL)
{
g_pcsSectionList = pcsSection;
}
else
{
g_pcsSectionList->AddToList(pcsSection);
}
dwErr = pcsSection->SetSectionTitle((ptsSpecialName == NULL) ?
ptsRoot :
ptsSpecialName);
if (dwErr)
{
return dwErr;
}
dwErr = pcsSection->SetSectionPath(ptsRoot);
if (dwErr)
{
return dwErr;
}
}
if (_tcslen(ptsRoot) + 3 >= MAX_PATH)
{
if (DebugOutput)
{
Win32Printf(LogFile, "Error: ptsRoot too long %s\r\n", ptsRoot);
}
return ERROR_FILENAME_EXCED_RANGE;
}
_tcscpy(ptsStart, ptsRoot);
_tcscat(ptsStart, TEXT("*.*"));
hNext = FindFirstFile(ptsStart, &wfd);
if (hNext == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_FILE_ENUMFAIL, ptsStart);
return dwErr;
}
//Files first, then directories
do
{
CRuleList *prl = NULL;
DWORD dwIndex;
TCHAR *ptsName = ((wfd.cFileName) ?
wfd.cFileName :
wfd.cAlternateFileName);
if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
IncludeFile(ptsRoot, ptsName, &wfd, &prl))
{
ULONG i;
TCHAR buf[MAX_PATH+1];
TCHAR *ptsScratch;
ptsScratch = ptsRoot + pcsSection->GetSectionPathLength() + 1;
if (_tcslen(ptsScratch) + _tcslen(ptsName) > MAX_PATH)
{
if (DebugOutput)
{
Win32Printf(LogFile, "Error: buf too long %s%s\r\n", ptsScratch, ptsName);
}
return ERROR_FILENAME_EXCED_RANGE;
}
_tcscpy(buf, ptsScratch);
_tcscat(buf, ptsName);
// Win32Printf(STDOUT, "%s%s\r\n", ptsRoot, ptsName);
dwErr = pcsSection->SetName(buf, &i, FALSE);
if (dwErr)
return dwErr;
if ((prl != NULL) && (prl->GetDestination() != NULL))
{
dwErr = pcsSection->SetDestination(
prl->GetDestination(),
i);
if (dwErr)
return dwErr;
}
}
}
while (0 != FindNextFile(hNext, &wfd));
hNext = FindFirstFile(ptsStart, &wfd);
if (hNext == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_FILE_ENUMFAIL, ptsStart);
return dwErr;
}
do
{
TCHAR ptsPath[MAX_PATH + 1];
TCHAR *ptsName = ((wfd.cFileName) ?
wfd.cFileName :
wfd.cAlternateFileName);
if (_tcslen(ptsRoot) + _tcslen(ptsName) + 1 > MAX_PATH)
{
if (DebugOutput)
{
Win32Printf(LogFile, "Error: filename too long %s%s\\\r\n", ptsRoot, ptsName);
}
return ERROR_FILENAME_EXCED_RANGE;
}
_tcscpy(ptsPath, ptsRoot);
_tcscat(ptsPath, ptsName);
_tcscat(ptsPath, TEXT("\\"));
if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
_tcscmp(ptsName, TEXT(".")) &&
_tcscmp(ptsName, TEXT("..")))
{
if (IncludeFile(ptsPath, NULL, &wfd, NULL) ||
IncludeDirectory(ptsPath, &wfd))
{
ProcessFileTree(ptsPath, pcsSection, cRecursionLevel + 1);
}
}
}
while (0 != FindNextFile(hNext, &wfd));
return 0;
}
DWORD AddInfSectionToRuleList(INFCONTEXT *pic,
CRuleList *pfl,
BOOL fAllowRename)
{
TCHAR buf[MAX_PATH + 1];
TCHAR bufMacro[MAX_PATH + 1];
TCHAR *ptsFinalName;
TCHAR bufTag[MAX_PATH + 1];
DWORD dwErr;
CRuleList *prl;
do
{
DWORD dwIndex;
DWORD cFields;
BOOL fDirectoryTag = FALSE;
cFields = SetupGetFieldCount(pic);
if (((cFields != 1) && !fAllowRename) ||
((cFields > 2) && fAllowRename))
{
Win32PrintfResource(LogFile, IDS_INF_ERROR);
if (Verbose)
Win32Printf(STDERR,
"Line contains more than one file name\r\n");
return ERROR_INVALID_PARAMETER;
}
if (!SetupGetStringField(pic,
1,
buf,
MAX_PATH + 1,
NULL))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_INF_ERROR);
if (Verbose)
Win32Printf(STDERR,
"SetupGetStringField returned %lu\r\n",
dwErr);
return dwErr;
}
if (SetupGetStringField(pic,
0,
bufTag,
MAX_PATH + 1,
NULL))
{
if (_tcsicmp(bufTag, buf))
{
//Someone put a field identifier on there. The only
//one we recognize is 'dir'
if (_tcsicmp(bufTag, TEXT("dir")))
{
Win32PrintfResource(LogFile, IDS_INF_ERROR);
if (Verbose)
Win32Printf(STDERR,
"Unknown tag %s\r\n",
bufTag);
return ERROR_INVALID_PARAMETER;
}
fDirectoryTag = TRUE;
}
}
dwErr = g_csd.ExpandMacro(buf, bufMacro, &ptsFinalName, TRUE);
if (dwErr)
return dwErr;
DWORD ccFinalName = _tcslen(ptsFinalName);
if ((fDirectoryTag) && (ptsFinalName[ccFinalName-1] != '\\'))
{
//Append a backslash if there isn't one already
if (ccFinalName > MAX_PATH)
{
if (DebugOutput)
{
Win32Printf(LogFile, "Error: ptsFinalName too long: %s\\\r\n", ptsFinalName);
}
return ERROR_FILENAME_EXCED_RANGE;
}
else
{
_tcscat(ptsFinalName, TEXT("\\"));
}
}
dwErr = pfl->SetName(ptsFinalName, &prl);
if (dwErr)
{
return dwErr;
}
if (cFields == 2)
{
if (!SetupGetStringField(pic,
2,
buf,
MAX_PATH + 1,
NULL))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_INF_ERROR);
if (Verbose)
Win32Printf(STDERR,
"SetupGetStringField returned %lu\r\n",
dwErr);
return dwErr;
}
dwErr = prl->SetDestination(buf);
if (dwErr)
{
return dwErr;
}
}
}
while (SetupFindNextLine(pic, pic));
return ERROR_SUCCESS;
}
DWORD ProcessCopyFiles(HINF hi, const TCHAR *ptsName)
{
DWORD dwErr;
INFCONTEXT ic;
if (!SetupFindFirstLine(hi,
ptsName,
NULL,
&ic))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_SECTION_NAME_NOT_FOUND, ptsName);
if (Verbose)
Win32Printf(STDERR,
"SetupFindFirstLine failed on section %s with %lu\r\n",
ptsName,
dwErr);
return dwErr;
}
dwErr = AddInfSectionToRuleList(&ic, &g_crlIncludeWildcards, TRUE);
return dwErr;
}
DWORD ProcessDelFiles(HINF hi, const TCHAR *ptsName)
{
DWORD dwErr;
INFCONTEXT ic;
if (!SetupFindFirstLine(hi,
ptsName,
NULL,
&ic))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_SECTION_NAME_NOT_FOUND, ptsName);
if (Verbose)
Win32Printf(STDERR,
"SetupFindFirstLine failed on section %s with %lu\r\n",
ptsName,
dwErr);
return dwErr;
}
dwErr = AddInfSectionToRuleList(&ic, &g_crlExcludeWildcards, FALSE);
return dwErr;
}
DWORD ProcessSysFiles(HINF hi, const TCHAR *ptsName)
{
DWORD dwErr;
INFCONTEXT ic;
if (!SetupFindFirstLine(hi,
ptsName,
NULL,
&ic))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_SECTION_NAME_NOT_FOUND, ptsName);
if (Verbose)
Win32Printf(STDERR,
"SetupFindFirstLine failed on section %s with %lu\r\n",
ptsName,
dwErr);
return dwErr;
}
LONG cLines = SetupGetLineCount(hi,
ptsName);
if (cLines == -1)
{
//Error
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_INF_ERROR);
if (Verbose)
Win32Printf(STDERR,
"Couldn't get line count for System Files section\r\n");
return ERROR_INVALID_PARAMETER;
}
g_sfl.SetInitialSize(cLines);
TCHAR buf[MAX_PATH + 1];
TCHAR bufMacro[MAX_PATH + 1];
TCHAR *ptsFinalName;
do
{
DWORD cFields;
cFields = SetupGetFieldCount(&ic);
if (cFields != 1)
{
Win32PrintfResource(LogFile, IDS_INF_ERROR);
if (Verbose)
Win32Printf(STDERR,
"Sys file line contains multiple fields\r\n");
return ERROR_INVALID_PARAMETER;
}
if (!SetupGetStringField(&ic,
1,
buf,
MAX_PATH + 1,
NULL))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_INF_ERROR);
if (Verbose)
Win32Printf(STDERR,
"SetupGetStringField returned %lu\r\n",
dwErr);
return dwErr;
}
dwErr = g_csd.ExpandMacro(buf, bufMacro, &ptsFinalName, TRUE);
if (dwErr)
return dwErr;
//Add the name to the sys file list
dwErr = g_sfl.AddName(ptsFinalName);
if (dwErr)
return dwErr;
} while (SetupFindNextLine(&ic, &ic));
return ERROR_SUCCESS;
}
DWORD ParseInputFile(HINF hi)
{
DWORD dwErr;
INFCONTEXT ic;
if (!SetupFindFirstLine(hi,
EXTENSION_SECTION,
NULL,
&ic))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile,
IDS_SECTION_NAME_NOT_FOUND,
EXTENSION_SECTION);
if (Verbose)
Win32Printf(STDERR,
"SetupFindFirstLine failed with %lu\r\n", dwErr);
return dwErr;
}
do
{
DWORD cFields;
cFields = SetupGetFieldCount(&ic);
TCHAR buf[MAX_PATH + 1];
if (!SetupGetStringField(&ic,
0,
buf,
MAX_PATH + 1,
NULL))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_INF_ERROR);
if (Verbose)
Win32Printf(STDERR,
"SetupGetStringField failed with %lu\r\n",
dwErr);
return dwErr;
}
if (_tcsicmp(buf, COPYFILES_LABEL) == 0)
{
//Add files in all sections to the include list
for (DWORD j = 1; j < cFields + 1; j++)
{
if (!SetupGetStringField(&ic,
j,
buf,
MAX_PATH + 1,
NULL))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_INF_ERROR);
if (Verbose)
Win32Printf(STDERR,
"SetupGetStringField failed with %lu\r\n",
dwErr);
return dwErr;
}
dwErr = ProcessCopyFiles(hi, buf);
if (dwErr != 0)
return dwErr;
}
}
else if (_tcsicmp(buf, DELFILES_LABEL) == 0)
{
//Add files in all sections to the include list
for (DWORD j = 1; j < cFields + 1; j++)
{
if (!SetupGetStringField(&ic,
j,
buf,
MAX_PATH + 1,
NULL))
{
dwErr = GetLastError();
Win32PrintfResource(LogFile, IDS_INF_ERROR);
if (Verbose)
Win32Printf(STDERR,
"SetupGetStringField failed with %lu\r\n",
dwErr);
return dwErr;
}
dwErr = ProcessDelFiles(hi, buf);
if (dwErr != 0)
return dwErr;
}
}
}
while (SetupFindNextLine(&ic, &ic));
return ERROR_SUCCESS;
}
DWORD OutputSectionList(CSection *pcs)
{
DWORD dwErr = ERROR_SUCCESS;
CSection *pcsTemp = pcs;
Win32Printf(OutputFile, "[%s]\r\n", COPYFILE_SECTION);
while (pcsTemp != NULL)
{
if (pcsTemp->GetNameCount() != 0)
Win32Printf(OutputFile,"%s\r\n", pcsTemp->GetSectionTitle());
pcsTemp = pcsTemp->GetNextSection();
}
Win32Printf(OutputFile, "\r\n");
pcsTemp = pcs;
while (pcsTemp != NULL)
{
if (pcsTemp->GetNameCount() != 0)
{
Win32Printf(OutputFile,"[%s]\r\n", pcsTemp->GetSectionTitle());
for (ULONG i = 0; i < pcsTemp->GetNameCount(); i++)
{
Win32Printf(OutputFile,"\"%s\"", pcsTemp->GetFullFileName(i));
if (pcsTemp->GetDestination(i) != NULL)
{
Win32Printf(OutputFile,",\"%s\"", pcsTemp->GetDestination(i));
}
Win32Printf(OutputFile, "\r\n");
if ((dwErr = CopyAFile(pcsTemp->GetSectionPath(),
pcsTemp->GetFullFileName(i))))
{
return dwErr;
}
}
Win32Printf(OutputFile, "\r\n");
}
pcsTemp = pcsTemp->GetNextSection();
}
pcsTemp = pcs;
DWORD dwSection = 10000;
Win32Printf(OutputFile, "[%s]\r\n", DESTINATIONDIRS_SECTION);
while (pcsTemp != NULL)
{
if (pcsTemp->GetNameCount() != 0)
{
Win32Printf(OutputFile,"%s=%lu\r\n",
pcsTemp->GetSectionTitle(),
dwSection++);
}
pcsTemp = pcsTemp->GetNextSection();
}
Win32Printf(OutputFile,"\r\n");
return dwErr;
}
void OutputSpecialDirectoryList(CSpecialDirectory *psd)
{
Win32Printf(OutputFile, "[%s]\r\n", SPECIALDIRS_SECTION);
for (ULONG i = 0; i < psd->GetDirectoryCount(); i++)
{
if (psd->GetDirectoryPath(i) != NULL)
{
Win32Printf(OutputFile,
"%s=\"%s\"\r\n",
psd->GetDirectoryName(i),
psd->GetDirectoryPath(i));
}
}
Win32Printf(OutputFile, "\r\n");
}
DWORD ScanFiles()
{
DWORD dwErr;
DWORD dwDrives;
TCHAR tcDriveName[5];
//If we're copying files, grab all the rules from the input file
//Otherwise, we'll only take things specified by PickUpThisFile
if (CopyFiles)
{
dwErr = ParseInputFile(InputInf);
if (dwErr)
return dwErr;
}
dwDrives = GetLogicalDrives();
for (int i = 0; i < 26; i++)
{
if (dwDrives & 1)
{
tcDriveName[0] = (TCHAR)'A' + i;
tcDriveName[1] = (TCHAR)':';
tcDriveName[2] = (TCHAR)'\\';
tcDriveName[3] = 0;
UINT uiDriveType = GetDriveType(tcDriveName);
TCHAR *tcDriveTypeName;
if (uiDriveType == DRIVE_FIXED)
{
ProcessFileTree(tcDriveName, NULL, 0);
}
else if (uiDriveType == DRIVE_NO_ROOT_DIR)
{
if (Verbose)
Win32Printf(STDERR,
"Warning: GetDriveType returned "
"DRIVE_NO_ROOT_DIR for drive %s\r\n",
tcDriveName);
}
}
dwDrives = dwDrives >> 1;
}
dwErr = OutputSectionList(g_pcsSectionList);
if (dwErr)
return dwErr;
OutputSpecialDirectoryList(&g_csd);
return ERROR_SUCCESS;
}