mirror of https://github.com/lianthony/NT4.0
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.
1223 lines
28 KiB
1223 lines
28 KiB
#include "setupp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
#define MAX_DOS_DRIVES 26
|
|
|
|
|
|
DWORD
|
|
DS_EnableDisableSection(
|
|
IN OUT HDS hDS,
|
|
IN HINF hInf,
|
|
IN PCWSTR lpcSection,
|
|
IN BOOL bIsEnable,
|
|
IN BOOL bAddSize
|
|
);
|
|
|
|
DWORD
|
|
DS_AddCopyDelSection(
|
|
IN OUT HDS hDS,
|
|
IN HINF hInf,
|
|
IN HINF hInfLayout,
|
|
IN PCWSTR lpszFileSection,
|
|
IN BOOL bIsCopy,
|
|
IN BOOL bIsEnable,
|
|
IN BOOL bAddSize
|
|
);
|
|
|
|
PDIR_REC
|
|
AddDirEntry(
|
|
IN HDS hDS,
|
|
IN PWSTR szPath,
|
|
OUT PDS_DRIVE *drvinfo
|
|
);
|
|
|
|
PFILE_REC
|
|
AddFileEntry(
|
|
IN PDS_DRIVE DriveDesc,
|
|
IN OUT PDIR_REC *DirDesc,
|
|
IN PWSTR szFile,
|
|
IN BOOL bIsCopy,
|
|
IN BOOL bIsEnable,
|
|
IN DWORD dwNewSize
|
|
);
|
|
|
|
PFILE_REC
|
|
UpdateExistingFile(
|
|
IN OUT PDIR_REC pDir,
|
|
IN PWIN32_FIND_DATA FindData
|
|
);
|
|
|
|
BYTE
|
|
HashName(
|
|
IN PCWSTR Name,
|
|
IN BYTE HashMask
|
|
);
|
|
|
|
|
|
HDS
|
|
DS_Init(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns a hash table handle.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Hash table handle.
|
|
|
|
--*/
|
|
|
|
{
|
|
PDS_DRIVE p;
|
|
DWORD d;
|
|
WCHAR root[4];
|
|
UINT OldMode;
|
|
DWORD spc,bps,fClus,tClus;
|
|
|
|
if(p = MyMalloc(sizeof(DS_DRIVE) * MAX_DOS_DRIVES)) {
|
|
|
|
ZeroMemory(p,sizeof(DS_DRIVE) * MAX_DOS_DRIVES);
|
|
|
|
OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
|
|
//
|
|
// For each drive, get the number of bytes in a cluster
|
|
// and the total drive size.
|
|
//
|
|
d = GetLogicalDrives();
|
|
|
|
root[0] = L'A';
|
|
root[1] = L':';
|
|
root[2] = '\\';
|
|
root[3] = 0;
|
|
|
|
while(d) {
|
|
|
|
if((d & 1)
|
|
&& (MyGetDriveType(root[0]) == DRIVE_FIXED)
|
|
&& GetDiskFreeSpace(root,&spc,&bps,&fClus,&tClus)) {
|
|
|
|
p[root[0]-L'A'].uBpc = spc*bps;
|
|
p[root[0]-L'A'].Total = (LONGLONG)UInt32x32To64(spc*bps,tClus);
|
|
|
|
} else {
|
|
//
|
|
// Dummy value. The rest is already zeroed out.
|
|
//
|
|
p[root[0]-L'A'].uBpc = 512;
|
|
}
|
|
|
|
d >>= 1;
|
|
root[0]++;
|
|
}
|
|
|
|
SetErrorMode(OldMode);
|
|
}
|
|
|
|
return(p);
|
|
}
|
|
|
|
|
|
VOID
|
|
DS_Destroy(
|
|
IN OUT HDS hDS
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destroys a hash table handle by freeing all nodes and then freeing
|
|
the drive table.
|
|
|
|
Arguments:
|
|
|
|
hDS - Supplies pointer to hash table handle created by DS_Init()
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
int i;
|
|
PDIR_REC pDir;
|
|
PDIR_REC pTmp;
|
|
|
|
//
|
|
// Simple parameter validation
|
|
//
|
|
if(!hDS) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop once for each MS-DOS drive letter
|
|
//
|
|
for(i=0; i<MAX_DOS_DRIVES; i++) {
|
|
|
|
//
|
|
// If this entry for this drive isn't NULL free all memory
|
|
// associated with the drive
|
|
//
|
|
if(pDir = hDS[i].lpDir) {
|
|
|
|
do {
|
|
|
|
pTmp = pDir->pNext;
|
|
MyFree(pDir);
|
|
pDir = pTmp;
|
|
|
|
} while(pDir);
|
|
}
|
|
}
|
|
|
|
MyFree(hDS);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DS_SsyncDrives(
|
|
IN HDS hDS
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Walks all the directories specified in the caller's hash table and
|
|
ssyncs the hash table file entries to any matching files in the
|
|
respective directory.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
TRUE if hDS is valid. FALSE if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
int i; // Loop indice
|
|
PDIR_REC lpDir; // Ptr to current dir record
|
|
PFILE_REC lpFile; // Ptr to current file record
|
|
WIN32_FIND_DATA fInfo;
|
|
HANDLE FindHandle;
|
|
WCHAR szPath[MAX_PATH]; // Current directory path
|
|
BOOL b;
|
|
BOOL NoFiles;
|
|
|
|
if(!hDS) {
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Loop once for each MS-DOS drive letter
|
|
//
|
|
for(i=0; i<MAX_DOS_DRIVES; i++) {
|
|
|
|
//
|
|
// Loop once for each directory entry with this drive
|
|
//
|
|
for(lpDir=hDS[i].lpDir; lpDir; lpDir=lpDir->pNext) {
|
|
|
|
lstrcpy(szPath,lpDir->Name);
|
|
lstrcat(szPath,L"\\*");
|
|
|
|
FindHandle = FindFirstFile(szPath,&fInfo);
|
|
if(FindHandle == INVALID_HANDLE_VALUE) {
|
|
b = FALSE;
|
|
} else {
|
|
//
|
|
// Ignore subdirectories
|
|
//
|
|
b = TRUE;
|
|
NoFiles = FALSE;
|
|
while(fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
if(!FindNextFile(FindHandle,&fInfo)) {
|
|
NoFiles = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check termination condition.
|
|
//
|
|
if(NoFiles) {
|
|
FindClose(FindHandle);
|
|
FindHandle = INVALID_HANDLE_VALUE;
|
|
b = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// For each file in this directory update its hash record
|
|
//
|
|
while(b) {
|
|
|
|
if(lpFile = UpdateExistingFile(lpDir,&fInfo)) {
|
|
//
|
|
// !!!ADD HERE!!!
|
|
// Update count of needed, tobefree'ed and existing
|
|
//
|
|
}
|
|
|
|
//
|
|
// Find next non-subdirectory.
|
|
//
|
|
b = TRUE;
|
|
do {
|
|
if(!FindNextFile(FindHandle,&fInfo)) {
|
|
//
|
|
// No more files.
|
|
//
|
|
b = FALSE;
|
|
break;
|
|
}
|
|
|
|
} while(fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
|
}
|
|
|
|
if(FindHandle != INVALID_HANDLE_VALUE) {
|
|
FindClose(FindHandle);
|
|
}
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DS_GetDriveData(
|
|
IN HDS hDS,
|
|
IN WCHAR chDrvLetter,
|
|
OUT PDS_DRIVE pDriveInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
hDS - supplies hash table pointer
|
|
|
|
chDrvLetter - supplies MS-DOS driver letter ('A','B','C',...)
|
|
|
|
pDriveInfo - supplies pointer to a hash table drive structure to be filled in
|
|
|
|
Return Value:
|
|
|
|
TRUE if valid hDS and drive letter else FALSE
|
|
|
|
--*/
|
|
|
|
{
|
|
int i; // Loop indice
|
|
DWORD dwCopy, dwDel; // Real uncompressed bytes needed
|
|
PDS_DRIVE pDrvData; // Ptr into hDS
|
|
PDIR_REC lpDir; // Ptr to current dir record
|
|
LONG lRequired; // Required disk space.
|
|
WCHAR szTmp[4];
|
|
DWORD FreeClus,TotalClus;
|
|
DWORD spc,bps;
|
|
|
|
|
|
//
|
|
// Simple parameter validation.
|
|
//
|
|
if(!pDriveInfo || !hDS) {
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Uppercase the drive letter.
|
|
//
|
|
chDrvLetter = (WCHAR)CharUpper((LPTSTR)chDrvLetter);
|
|
|
|
//
|
|
// If it is not a valid drive then bail.
|
|
//
|
|
if((chDrvLetter < L'A') || (chDrvLetter > L'Z')) {
|
|
|
|
ZeroMemory(pDriveInfo,sizeof(DS_DRIVE));
|
|
return(TRUE);
|
|
}
|
|
|
|
pDrvData = hDS + (unsigned)(chDrvLetter - L'A');
|
|
|
|
dwCopy = dwDel = 0;
|
|
|
|
//
|
|
// Loop once for each directory entry with this drive
|
|
//
|
|
for(lpDir=pDrvData->lpDir; lpDir; lpDir=lpDir->pNext) {
|
|
for(i=0; i<lpDir->NextFileIndex; i++) {
|
|
|
|
if(lpDir->pFile[i].CopyCnt) {
|
|
|
|
dwCopy += lpDir->pFile[i].dwNewSize;
|
|
dwDel += lpDir->pFile[i].Size;
|
|
|
|
} else {
|
|
|
|
if(lpDir->pFile[i].DelCnt) {
|
|
dwDel += lpDir->pFile[i].Size;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
lRequired = (LONG)(dwCopy - dwDel); // Note: may be negative.
|
|
|
|
|
|
//
|
|
// Get the disk space free
|
|
//
|
|
szTmp[0] = chDrvLetter;
|
|
szTmp[1] = L':';
|
|
szTmp[2] = L'\\';
|
|
szTmp[3] = 0;
|
|
|
|
if(GetDiskFreeSpace(szTmp,&spc,&bps,&FreeClus,&TotalClus)) {
|
|
|
|
pDrvData->Free = (LONGLONG)UInt32x32To64(spc*bps,FreeClus);
|
|
|
|
} else {
|
|
//
|
|
// Dummy values
|
|
//
|
|
spc = 1;
|
|
bps = 512;
|
|
FreeClus = 0;
|
|
TotalClus = 0;
|
|
pDrvData->Free = 0;
|
|
}
|
|
|
|
//
|
|
// Available is the same as free.
|
|
//
|
|
pDrvData->Available = pDrvData->Free;
|
|
|
|
pDrvData->Required = (lRequired > 0) ? (DWORD)lRequired : 0;
|
|
|
|
//
|
|
// Set caller's structure and return.
|
|
//
|
|
*pDriveInfo = *pDrvData;
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DS_EnableSection(
|
|
IN HDS hDS,
|
|
IN HINF hInf,
|
|
IN PCWSTR lpcSection
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enables a geninstall section in a caller's hash table.
|
|
|
|
Arguments:
|
|
|
|
hDS - Supplies hash table pointer
|
|
|
|
HINF - Supplies handle to open inf file
|
|
|
|
lpcSection - Pointer to name of section
|
|
|
|
Return Value:
|
|
|
|
Boolean value indicating outcome. FALSE = out of memory condition.
|
|
|
|
--*/
|
|
|
|
{
|
|
return(DS_EnableDisableSection(hDS,hInf,lpcSection,TRUE,FALSE) != (DWORD)(-1));
|
|
}
|
|
|
|
|
|
BOOL
|
|
DS_DisableSection(
|
|
IN HDS hDS,
|
|
IN HINF hInf,
|
|
IN PCWSTR lpcSection
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Disables a geninstall section in a caller's hash table.
|
|
|
|
Arguments:
|
|
|
|
hDS - Supplies hash table pointer
|
|
|
|
HINF - Supplies handle to open inf file
|
|
|
|
lpcSection - Pointer to name of section
|
|
|
|
Return Value:
|
|
|
|
Boolean value indicating outcome. FALSE = out of memory condition.
|
|
|
|
--*/
|
|
|
|
{
|
|
return(DS_EnableDisableSection(hDS,hInf,lpcSection,FALSE,FALSE) != (DWORD)(-1));
|
|
}
|
|
|
|
|
|
DWORD
|
|
DS_EnableDisableSection(
|
|
IN OUT HDS hDS,
|
|
IN HINF hInf,
|
|
IN PCWSTR lpcSection,
|
|
IN BOOL bIsEnable,
|
|
IN BOOL bAddSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enables or disables a geninstall section in a caller's hash table. This
|
|
function can also be used to create new entries in the hash table.
|
|
|
|
Arguments:
|
|
|
|
hDS - Supplies hash table pointer
|
|
|
|
HINF - supplies INF handle. The INF must be opened and the layout file
|
|
must already be append-opened.
|
|
|
|
lpcSection - Supplies pointer to geninstall section
|
|
|
|
bIsEnable - TRUE to enable this section else FALSE to disable it
|
|
|
|
bAddSize - TRUE to update new size else FALSE
|
|
|
|
Return Value:
|
|
|
|
Total number of bytes being installed by this section.
|
|
The value will be normalize to account for cluster
|
|
boundaries. On memory error returns -1.
|
|
|
|
--*/
|
|
|
|
{
|
|
int i;
|
|
HINF hInfTmp;
|
|
DWORD dwSize, dwTotal;
|
|
WCHAR szTmp[LINE_LEN];
|
|
PCWSTR apszDelCopyKeys[3];
|
|
BOOL b;
|
|
INFCONTEXT InfContext;
|
|
WCHAR SectionName[LINE_LEN];
|
|
LONG FieldCount;
|
|
DWORD DontCare;
|
|
LONG Field;
|
|
HINF hLayoutInf;
|
|
|
|
apszDelCopyKeys[0] = L"Delfiles";
|
|
apszDelCopyKeys[1] = L"Copyfiles";
|
|
apszDelCopyKeys[2] = NULL;
|
|
dwTotal = 0;
|
|
|
|
//
|
|
// Open/append layout inf -- cached. So we don't worry about closing it.
|
|
//
|
|
hLayoutInf = InfCacheOpenLayoutInf(hInf);
|
|
if(!hLayoutInf) {
|
|
return((DWORD)(-1));
|
|
}
|
|
|
|
for(i=0; i<2; i++) {
|
|
|
|
//
|
|
// Find Install Section and copy files entry. If not there then
|
|
// assume no files to copy. Assume there can be none or more than one.
|
|
//
|
|
b = SetupFindFirstLine(hInf,lpcSection,apszDelCopyKeys[i],&InfContext);
|
|
|
|
while(b) {
|
|
|
|
FieldCount = (LONG)SetupGetFieldCount(&InfContext);
|
|
|
|
//
|
|
// Handle each field on the line.
|
|
//
|
|
for(Field=0; Field<FieldCount; Field++) {
|
|
|
|
if(SetupGetStringField(&InfContext,Field+1,SectionName,LINE_LEN,&DontCare)) {
|
|
|
|
//
|
|
// Figure out how much disk space is required.
|
|
//
|
|
dwSize = DS_AddCopyDelSection(
|
|
hDS,
|
|
hInf,
|
|
hLayoutInf,
|
|
SectionName,
|
|
i,
|
|
bIsEnable,
|
|
bAddSize
|
|
);
|
|
|
|
if(dwSize == (DWORD)(-1)) {
|
|
|
|
return((DWORD)(-1));
|
|
}
|
|
|
|
//
|
|
// If doing a copy we need to keep track of total for del
|
|
//
|
|
if(i) {
|
|
dwTotal += dwSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
b = SetupFindNextMatchLine(&InfContext,apszDelCopyKeys[i],&InfContext);
|
|
}
|
|
}
|
|
|
|
return(dwTotal);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DS_AddSection(
|
|
IN HDS hDS,
|
|
IN HINF hInf,
|
|
IN PCWSTR lpcSection
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Adds a new geninstall section to a caller's hash table.
|
|
|
|
Arguments:
|
|
|
|
hDS - Hash table pointer
|
|
|
|
HINF - INF handle
|
|
|
|
lpcSection - Pointer to geninstall section
|
|
|
|
Return Value:
|
|
|
|
Total number of bytes being installed by this section.
|
|
The value will be normalize to account for cluster boundaries.
|
|
|
|
--*/
|
|
|
|
{
|
|
return(DS_EnableDisableSection(hDS,hInf,lpcSection,TRUE,TRUE));
|
|
}
|
|
|
|
|
|
DWORD
|
|
DS_AddCopyDelSection(
|
|
IN OUT HDS hDS,
|
|
IN HINF hInf,
|
|
IN HINF hInfLayout,
|
|
IN PCWSTR lpszFileSection,
|
|
IN BOOL bIsCopy,
|
|
IN BOOL bIsEnable,
|
|
IN BOOL bAddSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will calculate the disk space requirements for the a
|
|
particular "CopyFiles" section. This function also handles the special
|
|
@<filespec> case.
|
|
|
|
Arguments:
|
|
|
|
hDS - Supplies hash table pointer
|
|
|
|
hInf - Supplies open INF handle
|
|
|
|
hInfLayout - supplies open INF handle for layout file for hInf
|
|
|
|
lpszFileSection - Supplies pointer to Copyfiles/Delfiles section
|
|
|
|
bIsCopy - TRUE if file to be copied or FALSE it to be deleted
|
|
|
|
bIsEnable - TRUE to enable this section else FALSE to disable it
|
|
|
|
bAddSize - TRUE to update new size else FALSE
|
|
|
|
Return Value:
|
|
|
|
Total bytes in new files added or deleted.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT reRet;
|
|
PDIR_REC lpDir;
|
|
PFILE_REC lpFile;
|
|
DWORD dwSize;
|
|
DWORD dwTotal;
|
|
int uTmp;
|
|
WCHAR szPath[MAX_PATH];
|
|
WCHAR szBuf[MAX_PATH];
|
|
WCHAR szSourceFile[MAX_PATH];
|
|
WCHAR szTargetFile[MAX_PATH];
|
|
PWSTR szTmp;
|
|
BOOL b;
|
|
DWORD DontCare;
|
|
PDS_DRIVE DriveInfo;
|
|
INFCONTEXT InfContext;
|
|
PDS_DRIVE drvinfo;
|
|
|
|
|
|
dwTotal = 0;
|
|
DriveInfo = hDS;
|
|
|
|
if(!lpszFileSection[0]) {
|
|
return(0);
|
|
}
|
|
|
|
//
|
|
// Check for special @<filename> format which specifies a single filename
|
|
//
|
|
if(lpszFileSection[0] == '@') {
|
|
|
|
//
|
|
// Skip the '@' char
|
|
//
|
|
lstrcpyn(szSourceFile,++lpszFileSection,MAX_PATH);
|
|
|
|
//
|
|
// Get the file's target location.
|
|
//
|
|
if(SetupGetTargetPath(hInf,NULL,NULL,szPath,MAX_PATH,&DontCare)) {
|
|
|
|
//
|
|
// Add an entry for the directory.
|
|
//
|
|
lpDir = AddDirEntry(hDS,szPath,&drvinfo);
|
|
if(!lpDir) {
|
|
return((DWORD)(-1));
|
|
}
|
|
|
|
//
|
|
// Get the file's size (this is the size the file will be
|
|
// on the target). If the file isn't going to a local drive
|
|
// don't use cluster rounding.
|
|
//
|
|
dwSize = 0;
|
|
if(bIsCopy && bAddSize) {
|
|
|
|
if((szPath[0] >= L'A') && (szPath[0] <= L'Z') && (szPath[1] == L':')) {
|
|
b = TRUE;
|
|
} else {
|
|
b = FALSE;
|
|
}
|
|
|
|
b = SetupGetSourceFileSize(
|
|
hInfLayout,
|
|
NULL,
|
|
szSourceFile,
|
|
NULL,
|
|
&dwSize,
|
|
b ? DriveInfo[szPath[0] - L'A'].uBpc : 0
|
|
);
|
|
|
|
if(!b) {
|
|
dwSize = 0;
|
|
}
|
|
}
|
|
|
|
lpFile = AddFileEntry(drvinfo,&lpDir,szSourceFile,bIsCopy,bIsEnable,dwSize);
|
|
if(!lpFile) {
|
|
return((DWORD)(-1));
|
|
}
|
|
|
|
dwTotal = lpFile->dwNewSize;
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// Get the target for files in the given section.
|
|
//
|
|
if(SetupGetTargetPath(hInf,NULL,lpszFileSection,szPath,MAX_PATH,&DontCare)) {
|
|
|
|
//
|
|
// Add an entry for the directory.
|
|
//
|
|
lpDir = AddDirEntry(hDS,szPath,&drvinfo);
|
|
if(!lpDir) {
|
|
return((DWORD)(-1));
|
|
}
|
|
|
|
//
|
|
// Total the files listed in the section.
|
|
//
|
|
b = SetupFindFirstLine(hInf,lpszFileSection,NULL,&InfContext);
|
|
|
|
while(b) {
|
|
|
|
//
|
|
// Determine the source and target file names and
|
|
// get the file's size (this is the size the file will be
|
|
// on the target). If the file isn't going to a local drive
|
|
// don't use cluster rounding.
|
|
//
|
|
if(b = SetupGetStringField(&InfContext,1,szTargetFile,MAX_PATH,&DontCare)) {
|
|
|
|
if(!SetupGetStringField(&InfContext,2,szSourceFile,MAX_PATH,&DontCare)
|
|
|| !szSourceFile[0])
|
|
{
|
|
lstrcpy(szSourceFile,szTargetFile);
|
|
}
|
|
}
|
|
|
|
if(b) {
|
|
|
|
dwSize = 0;
|
|
if(bIsCopy && bAddSize) {
|
|
|
|
if((szPath[0] >= L'A') && (szPath[0] <= L'Z') && (szPath[1] == L':')) {
|
|
b = TRUE;
|
|
} else {
|
|
b = FALSE;
|
|
}
|
|
|
|
b = SetupGetSourceFileSize(
|
|
hInfLayout,
|
|
NULL,
|
|
szSourceFile,
|
|
NULL,
|
|
&dwSize,
|
|
b ? DriveInfo[szPath[0] - L'A'].uBpc : 0
|
|
);
|
|
|
|
if(!b) {
|
|
dwSize = 0;
|
|
}
|
|
}
|
|
|
|
lpFile = AddFileEntry(drvinfo,&lpDir,szTargetFile,bIsCopy,bIsEnable,dwSize);
|
|
if(!lpFile) {
|
|
return((DWORD)(-1));
|
|
}
|
|
|
|
dwTotal += lpFile->dwNewSize;
|
|
}
|
|
|
|
b = SetupFindNextMatchLine(&InfContext,NULL,&InfContext);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(dwTotal);
|
|
}
|
|
|
|
|
|
PFILE_REC
|
|
UpdateExistingFile(
|
|
IN OUT PDIR_REC pDir,
|
|
IN PWIN32_FIND_DATA FindData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locates and updates the hashed file entry for the specified file.
|
|
Will copy the file information passed by the caller into the hashed
|
|
file entry and then update various fields.
|
|
|
|
Arguments:
|
|
|
|
pDir - Points to an initialized directory name structure
|
|
|
|
pfInfo - Points to file info structure
|
|
|
|
Return Value:
|
|
|
|
TRUE if hDS is valid. FALSE if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
BYTE Hash; // Hash value for szFile
|
|
PFILE_REC pFile; // Pointer to file record
|
|
|
|
//
|
|
// Create hash value for filename
|
|
//
|
|
Hash = HashName(FindData->cFileName,HASH_MASK);
|
|
|
|
//
|
|
// Walk linked list of files with this hash value looking for
|
|
// a matching name
|
|
//
|
|
for(pFile = pDir->apFileHash[Hash]; pFile; pFile=pFile->pHashNext) {
|
|
|
|
if(!lstrcmpi(FindData->cFileName,pFile->Name)) {
|
|
|
|
//
|
|
// Found the filename in our hash list so save its info
|
|
//
|
|
pFile->Attrib = FindData->dwFileAttributes;
|
|
pFile->Size = FindData->nFileSizeLow;
|
|
|
|
FileTimeToDosDateTime(&FindData->ftLastWriteTime,&pFile->Date,&pFile->Time);
|
|
|
|
lstrcpyn(pFile->Name,FindData->cFileName,MAX_PATH);
|
|
|
|
//
|
|
// Normalize the size to a cluster boundary
|
|
//
|
|
pFile->Size = (pFile->Size + pDir->uBpc - 1) & (~((DWORD)pDir->uBpc - 1));
|
|
|
|
return(pFile);
|
|
}
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
PDIR_REC
|
|
AddDirEntry(
|
|
IN HDS hDS,
|
|
IN PWSTR szPath,
|
|
OUT PDS_DRIVE *drvinfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates and inserts a directory record into a record list searching
|
|
for duplicates before ceating a new record.
|
|
|
|
Arguments:
|
|
|
|
hDS - supplies drive info structure
|
|
|
|
szPath - Supplies pointer to a directory string
|
|
|
|
Return Value:
|
|
|
|
Pointer to directory record for specified directory
|
|
|
|
--*/
|
|
|
|
{
|
|
int iDrv; // Index into apDrvRec[]
|
|
BYTE hash; // Hash value for szFile
|
|
PDIR_REC pDir; // Pointer into existing list
|
|
PDIR_REC pNew; // Pointer to new record
|
|
|
|
|
|
CharUpper(szPath);
|
|
|
|
//
|
|
// Get pointer to head of the list and create a hash value for
|
|
// path string so we can search with it
|
|
//
|
|
iDrv = (int)((WCHAR)CharUpper((LPTSTR)*szPath) - L'A');
|
|
pDir = hDS[iDrv].lpDir;
|
|
hash = HashName(szPath,HASH_MASK);
|
|
*drvinfo = &hDS[iDrv];
|
|
|
|
//
|
|
// See if filename already exists in list for this directory
|
|
// by matching hash values and then name strings
|
|
//
|
|
for(pNew=pDir; pNew; pNew=pNew->pNext) {
|
|
|
|
if((hash == pNew->DirHash) && !lstrcmp(szPath,pNew->Name)) {
|
|
//
|
|
// Return ptr to existing record
|
|
//
|
|
return(pNew);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Didn't find a matching entry so add a new one to the list
|
|
// inserting it at the begining of the list. Inserting at the
|
|
// begining will reduce the search time for average case where
|
|
// alot of files will be in the same directory.
|
|
//
|
|
if(pNew = MyMalloc(sizeof(DIR_REC))) {
|
|
|
|
ZeroMemory(pNew,sizeof(DIR_REC));
|
|
|
|
lstrcpy(pNew->Name,szPath); // Copy the directory path
|
|
pNew->DirHash = hash; // Save the path hash
|
|
pNew->pNext = hDS[iDrv].lpDir; // Point new record to old head
|
|
hDS[iDrv].lpDir = pNew; // Put new record at head of list
|
|
pNew->uBpc = hDS[iDrv].uBpc; // Get bytes per sector on drive
|
|
}
|
|
|
|
return(pNew); // Return ptr to new record
|
|
}
|
|
|
|
|
|
PFILE_REC
|
|
AddFileEntry(
|
|
IN PDS_DRIVE DriveDesc,
|
|
IN OUT PDIR_REC *DirDesc,
|
|
IN PWSTR szFile,
|
|
IN BOOL bIsCopy,
|
|
IN BOOL bIsEnable,
|
|
IN DWORD dwNewSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a filename records for the directory specified by pDir. Will
|
|
check for duplicate names and if none is found will create a new
|
|
record for this file and add it to the end of the file record list
|
|
pointed to by pDir->File.
|
|
|
|
Arguments:
|
|
|
|
DirDesc - Supplies pointer to an initialized directory name structure
|
|
|
|
szFile - Supplies pointer to a the filename to be added
|
|
|
|
bIsCopy - TRUE if from CopyFile section or FALSE if from DelFile
|
|
|
|
bIsEnable - TRUE to enable this section else FALSE to disable it
|
|
|
|
dwNewSize - Size of file being added
|
|
|
|
Return Value:
|
|
|
|
Pointer to file record for specified file
|
|
|
|
--*/
|
|
|
|
{
|
|
BYTE Hash;
|
|
PDIR_REC fpTmp,pTmp;
|
|
PFILE_REC pFile;
|
|
WCHAR szTmp[MAX_PATH];
|
|
PDIR_REC pDir;
|
|
int i;
|
|
|
|
CharUpper(szFile);
|
|
pDir = *DirDesc;
|
|
|
|
//
|
|
// Create hash value for filename
|
|
//
|
|
Hash = HashName(szFile,HASH_MASK);
|
|
|
|
//
|
|
// Walk linked list of files with this hash value looking for
|
|
// a duplicate name
|
|
//
|
|
for(pFile=pDir->apFileHash[Hash]; pFile; pFile=pFile->pHashNext) {
|
|
|
|
if(!lstrcmp(szFile,pFile->Name)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!pFile) {
|
|
|
|
//
|
|
// Re-allocate array if no more free entries. We can determine
|
|
// if free entries are left by ANDing with (FILE_INCR - 1) because
|
|
// we know file increment is LOG2 value.
|
|
//
|
|
if(!(pDir->NextFileIndex & FILE_INCR_MASK)) {
|
|
|
|
//
|
|
// Remember who pointed to the DIR_REC we're going to rellocate.
|
|
//
|
|
if(pDir != DriveDesc->lpDir) {
|
|
for(pTmp=DriveDesc->lpDir; pTmp; pTmp=pTmp->pNext) {
|
|
if(pTmp->pNext == pDir) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
fpTmp = MyRealloc(
|
|
pDir,
|
|
offsetof(DIR_REC,pFile) + ((pDir->NextFileIndex + FILE_INCR) * sizeof(FILE_REC))
|
|
);
|
|
|
|
if(fpTmp == NULL) {
|
|
return(NULL);
|
|
}
|
|
|
|
//
|
|
// Zero out the newly reallocated part.
|
|
//
|
|
ZeroMemory(
|
|
(PUCHAR)fpTmp + offsetof(DIR_REC,pFile) + (fpTmp->NextFileIndex * sizeof(FILE_REC)),
|
|
FILE_INCR * sizeof(FILE_REC)
|
|
);
|
|
|
|
//
|
|
// Fix up the previous entry in the linked list.
|
|
//
|
|
if(pDir == DriveDesc->lpDir) {
|
|
DriveDesc->lpDir = fpTmp;
|
|
} else {
|
|
if(pTmp) {
|
|
pTmp->pNext = fpTmp;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now go through and fix up FILE_REC pointers.
|
|
//
|
|
for(i=0; i<MAX_HASH; i++) {
|
|
if(fpTmp->apFileHash[i]) {
|
|
|
|
(PUCHAR)fpTmp->apFileHash[i] += (DWORD)fpTmp - (DWORD)pDir;
|
|
|
|
//
|
|
// Now fix up pointers in linked list of files
|
|
// with this hash value. The loop continuation condition
|
|
// doesn't bother to check pFile because the 'if' above
|
|
// checked it already.
|
|
//
|
|
for(pFile=fpTmp->apFileHash[i]; pFile->pHashNext; pFile=pFile->pHashNext) {
|
|
|
|
(PUCHAR)pFile->pHashNext += (DWORD)fpTmp - (DWORD)pDir;
|
|
}
|
|
}
|
|
}
|
|
|
|
pDir = fpTmp;
|
|
*DirDesc = pDir;
|
|
}
|
|
|
|
//
|
|
// Get pointer to new record and then fill in the record
|
|
// pFile = pDir->pFile + pDir->NextFileIndex;
|
|
//
|
|
pFile = &pDir->pFile[pDir->NextFileIndex];
|
|
|
|
//
|
|
// Set size of new file normalize to cluster boundaries
|
|
//
|
|
if(dwNewSize) {
|
|
pFile->dwNewSize = (dwNewSize + pDir->uBpc - 1) & (~((DWORD)pDir->uBpc - 1));
|
|
}
|
|
|
|
pFile->Hash = Hash;
|
|
lstrcpy(pFile->Name,szFile);
|
|
|
|
//
|
|
// Insert new file record at head of linked hash list
|
|
//
|
|
pFile->pHashNext = pDir->apFileHash[Hash];
|
|
pDir->apFileHash[Hash] = pFile;
|
|
|
|
//
|
|
// Update indext to next new record
|
|
//
|
|
pDir->NextFileIndex++;
|
|
|
|
} else {
|
|
//
|
|
// If a delfile for this file was done first then make sure that we
|
|
// update the size in the node to the size that was passed in for the
|
|
// copy file entry.
|
|
//
|
|
if(bIsCopy && !pFile->dwNewSize) {
|
|
pFile->dwNewSize = (dwNewSize + pDir->uBpc - 1) & (~((DWORD)pDir->uBpc - 1));
|
|
}
|
|
}
|
|
|
|
if(bIsEnable) {
|
|
if(bIsCopy) {
|
|
pFile->CopyCnt++;
|
|
}
|
|
pFile->DelCnt++;
|
|
} else {
|
|
if(bIsCopy && pFile->CopyCnt) {
|
|
pFile->CopyCnt--;
|
|
}
|
|
if(pFile->DelCnt) {
|
|
pFile->DelCnt--;
|
|
}
|
|
}
|
|
|
|
return(pFile);
|
|
}
|
|
|
|
|
|
BYTE
|
|
HashName(
|
|
IN PCWSTR Name,
|
|
IN BYTE HashMask
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a simple hash value from a file name string by adding
|
|
all characters in the string together.
|
|
|
|
Arguments:
|
|
|
|
Name - Ptr to file name string
|
|
|
|
HashMask - supplies value to be anded with the final sum
|
|
to produce the final hash value.
|
|
|
|
Return Value:
|
|
|
|
BYTE sum of all characters in Name string ANDed with the given mask.
|
|
0 is never returned.
|
|
|
|
--*/
|
|
|
|
{
|
|
int Hash;
|
|
|
|
//
|
|
// Add the values of all the chars in the string.
|
|
//
|
|
Hash = 0;
|
|
while(*Name) {
|
|
Hash += (int)towlower(*(Name++));
|
|
}
|
|
|
|
//
|
|
// Don't allow a zero hash value.
|
|
//
|
|
if(!Hash) {
|
|
Hash = 1;
|
|
}
|
|
|
|
return((BYTE)(Hash & HashMask));
|
|
}
|