1040 lines
28 KiB
C
1040 lines
28 KiB
C
#include "precomp.h"
|
|
#pragma hdrstop
|
|
/**************************************************************************/
|
|
/***** Common Library Component - INF File Handling Routines 1 ***********/
|
|
/**************************************************************************/
|
|
|
|
|
|
BOOL APIENTRY FMatchPrefix(PSZ, SZ, BOOL);
|
|
GRC APIENTRY GrcHandleSfdOption(INT, POER, UINT);
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Allocates an Object Element Record and initializes it as empty.
|
|
** Arguments:
|
|
** none
|
|
** Returns:
|
|
** NULL if allocation fails.
|
|
** non-NULL pointer to the empty (initialized) Object Element Record.
|
|
**
|
|
**************************************************************************/
|
|
POER APIENTRY PoerAlloc(VOID)
|
|
{
|
|
POER poer;
|
|
|
|
AssertDataSeg();
|
|
|
|
if ((poer = (POER)SAlloc((CB)sizeof(OER))) != (POER)NULL)
|
|
{
|
|
poer->oef = oefNone;
|
|
poer->ctuCopyTime = (CTU)0;
|
|
poer->owm = owmAlways;
|
|
poer->lSize = 0L;
|
|
poer->szRename = (SZ)NULL;
|
|
poer->szAppend = (SZ)NULL;
|
|
poer->szBackup = (SZ)NULL;
|
|
poer->szDescription = (SZ)NULL;
|
|
poer->ulVerMS = 0L;
|
|
poer->ulVerLS = 0L;
|
|
poer->szDate = (SZ)NULL;
|
|
poer->szDest = (SZ)NULL; /* REVIEW EBU */
|
|
}
|
|
|
|
return(poer);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Free an Object Element Record and any non-empty string fields.
|
|
** Arguments:
|
|
** poer: non-NULL Object Element Record to be freed.
|
|
** Returns:
|
|
** fFalse if a freeing error occurs.
|
|
** fTrue for success.
|
|
**
|
|
**************************************************************************/
|
|
BOOL APIENTRY FFreePoer(poer)
|
|
POER poer;
|
|
{
|
|
AssertDataSeg();
|
|
|
|
ChkArg(poer != (POER)NULL, 1, fFalse);
|
|
|
|
if (poer->szRename != (SZ)NULL)
|
|
SFree(poer->szRename);
|
|
|
|
if (poer->szAppend != (SZ)NULL)
|
|
SFree(poer->szAppend);
|
|
|
|
if (poer->szBackup != (SZ)NULL)
|
|
SFree(poer->szBackup);
|
|
|
|
if (poer->szDescription != (SZ)NULL)
|
|
SFree(poer->szDescription);
|
|
|
|
if (poer->szDate != (SZ)NULL)
|
|
SFree(poer->szDate);
|
|
|
|
if (poer->szDest != (SZ)NULL) /* REVIEW EBU */
|
|
SFree(poer->szDest);
|
|
|
|
SFree(poer);
|
|
|
|
return(fTrue);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Validates an Option Element Record.
|
|
** Arguments:
|
|
** poer: non-Null pointer to OER to validate.
|
|
** Returns:
|
|
** fFalse if not valid.
|
|
** fTrue if valid.
|
|
**
|
|
**************************************************************************/
|
|
BOOL APIENTRY FValidPoer(poer)
|
|
POER poer;
|
|
{
|
|
AssertDataSeg();
|
|
|
|
ChkArg(poer != (POER)NULL, 1, fFalse);
|
|
|
|
if (poer->szBackup != (SZ)NULL &&
|
|
poer->szAppend != (SZ)NULL)
|
|
return(fFalse);
|
|
|
|
if (poer->szRename != (SZ)NULL &&
|
|
poer->szAppend != (SZ)NULL)
|
|
return(fFalse);
|
|
|
|
if (poer->szRename != (SZ)NULL &&
|
|
poer->oef & oefRoot)
|
|
return(fFalse);
|
|
|
|
if (poer->szAppend != (SZ)NULL &&
|
|
poer->oef & oefRoot)
|
|
return(fFalse);
|
|
|
|
if (poer->szRename != (SZ)NULL &&
|
|
CchlValidSubPath(poer->szRename) == (CCHL)0)
|
|
return(fFalse);
|
|
|
|
if (poer->szAppend != (SZ)NULL &&
|
|
CchlValidSubPath(poer->szAppend) == (CCHL)0)
|
|
return(fFalse);
|
|
|
|
if (poer->szBackup != (SZ)NULL &&
|
|
(*(poer->szBackup) != '*' ||
|
|
*(poer->szBackup + 1) != '\0') &&
|
|
CchlValidSubPath(poer->szBackup) == (CCHL)0)
|
|
return(fFalse);
|
|
|
|
if (poer->szDate != (SZ)NULL &&
|
|
!FValidOerDate(poer->szDate))
|
|
return(fFalse);
|
|
|
|
if (poer->lSize < 0L)
|
|
return(fFalse);
|
|
|
|
if (poer->owm != owmNever &&
|
|
poer->owm != owmAlways &&
|
|
poer->owm != owmUnprotected &&
|
|
poer->owm != owmOlder &&
|
|
poer->owm != owmVerifySourceOlder)
|
|
return(fFalse);
|
|
|
|
/* REVIEW EBU - no checking for szDest field */
|
|
|
|
return(fTrue);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Allocates a Section File Descriptor and initializes it as empty.
|
|
** Arguments:
|
|
** none
|
|
** Returns:
|
|
** NULL if allocation fails.
|
|
** non-NULL pointer to the empty (initialized) Section File Descriptor.
|
|
**
|
|
**************************************************************************/
|
|
PSFD APIENTRY PsfdAlloc(VOID)
|
|
{
|
|
PSFD psfd;
|
|
|
|
AssertDataSeg();
|
|
|
|
if ((psfd = (PSFD)SAlloc((CB)sizeof(SFD))) != (PSFD)NULL)
|
|
{
|
|
POER poer = &(psfd->oer);
|
|
|
|
psfd->did = didMin;
|
|
psfd->szFile = (SZ)NULL;
|
|
|
|
poer->oef = oefNone;
|
|
poer->ctuCopyTime = (CTU)0;
|
|
poer->owm = owmAlways;
|
|
poer->lSize = 0L;
|
|
poer->szRename = (SZ)NULL;
|
|
poer->szAppend = (SZ)NULL;
|
|
poer->szBackup = (SZ)NULL;
|
|
poer->szDescription = (SZ)NULL;
|
|
poer->ulVerMS = 0L;
|
|
poer->ulVerLS = 0L;
|
|
poer->szDate = (SZ)NULL;
|
|
poer->szDest = (SZ)NULL; /* REVIEW EBU */
|
|
}
|
|
|
|
return(psfd);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Free a Section File Descriptor and any non-empty string fields.
|
|
** Arguments:
|
|
** psfd: non-NULL Section File Descriptor to be freed.
|
|
** Returns:
|
|
** fFalse if a freeing error occurs.
|
|
** fTrue for success.
|
|
**
|
|
**************************************************************************/
|
|
BOOL APIENTRY FFreePsfd(psfd)
|
|
PSFD psfd;
|
|
{
|
|
AssertDataSeg();
|
|
|
|
ChkArg(psfd != (PSFD)NULL, 1, fFalse);
|
|
|
|
if (psfd->szFile != (SZ)NULL)
|
|
SFree(psfd->szFile);
|
|
|
|
if ((psfd->oer).szRename != (SZ)NULL)
|
|
SFree((psfd->oer).szRename);
|
|
|
|
if ((psfd->oer).szAppend != (SZ)NULL)
|
|
SFree((psfd->oer).szAppend);
|
|
|
|
if ((psfd->oer).szBackup != (SZ)NULL)
|
|
SFree((psfd->oer).szBackup);
|
|
|
|
if ((psfd->oer).szDescription != (SZ)NULL)
|
|
SFree((psfd->oer).szDescription);
|
|
|
|
if ((psfd->oer).szDate != (SZ)NULL)
|
|
SFree((psfd->oer).szDate);
|
|
|
|
if ((psfd->oer).szDest != (SZ)NULL)
|
|
SFree((psfd->oer).szDest);
|
|
|
|
SFree(psfd);
|
|
|
|
return(fTrue);
|
|
}
|
|
|
|
|
|
#if DBG
|
|
/*
|
|
** Purpose:
|
|
** Validates a Section File Descriptor.
|
|
** Arguments:
|
|
** psfd: non-Null pointer to SFD to validate.
|
|
** Returns:
|
|
** fFalse if not valid.
|
|
** fTrue if valid.
|
|
**
|
|
**************************************************************************/
|
|
BOOL APIENTRY FValidPsfd(psfd)
|
|
PSFD psfd;
|
|
{
|
|
AssertDataSeg();
|
|
|
|
ChkArg(psfd != (PSFD)NULL, 1, fFalse);
|
|
|
|
if (psfd->did < didMin ||
|
|
psfd->did > didMost ||
|
|
psfd->szFile == (SZ)NULL ||
|
|
CchlValidSubPath(psfd->szFile) == (CCHP)0)
|
|
return(fFalse);
|
|
|
|
return(FValidPoer(&(psfd->oer)));
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Purpose:
|
|
** Validates a Section File Descriptor Date string of the form
|
|
** "YYYY-MM-DD" where YYYY is >= 1980 and <= 2099, MM in [01..12],
|
|
** and DD in [01..31].
|
|
** Arguments:
|
|
** sz: non-Null Date string to validate.
|
|
** Returns:
|
|
** fFalse if invalid.
|
|
** fTrue if valid.
|
|
**
|
|
**************************************************************************/
|
|
BOOL APIENTRY FValidOerDate(sz)
|
|
SZ sz;
|
|
{
|
|
AssertDataSeg();
|
|
|
|
ChkArg(sz != (SZ)NULL, 1, fFalse);
|
|
|
|
if (*sz == '\0' ||
|
|
strlen(sz) != (CCHP)10 ||
|
|
!isdigit(*(sz + 0)) ||
|
|
!isdigit(*(sz + 1)) ||
|
|
!isdigit(*(sz + 2)) ||
|
|
!isdigit(*(sz + 3)) ||
|
|
!isdigit(*(sz + 5)) ||
|
|
!isdigit(*(sz + 6)) ||
|
|
!isdigit(*(sz + 8)) ||
|
|
!isdigit(*(sz + 9)) ||
|
|
*(sz + 4) != '-' ||
|
|
*(sz + 7) != '-')
|
|
return(fFalse);
|
|
|
|
if (*sz == '0' ||
|
|
*sz > '2' ||
|
|
(*sz == '1' &&
|
|
(*(sz + 1) != '9' ||
|
|
*(sz + 2) < '8')) ||
|
|
(*sz == '2' &&
|
|
*(sz + 1) != '0'))
|
|
return(fFalse);
|
|
|
|
if (*(sz + 5) > '1' ||
|
|
(*(sz + 5) == '0' &&
|
|
*(sz + 6) == '0') ||
|
|
(*(sz + 5) == '1' &&
|
|
*(sz + 6) > '2'))
|
|
return(fFalse);
|
|
|
|
if (*(sz + 8) > '3' ||
|
|
(*(sz + 8) == '0' &&
|
|
*(sz + 9) == '0') ||
|
|
(*(sz + 8) == '3' &&
|
|
*(sz + 9) > '1'))
|
|
return(fFalse);
|
|
|
|
return(fTrue);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Ensures rest of SFD option string matches (case insensitive compare)
|
|
** and consumes option string through matching portion and a trailing
|
|
** equals sign (if required).
|
|
** Arguments:
|
|
** psz: non-NULL pointer to non-NULL option string to match.
|
|
** szToMatch: non-Null uppercase string to match.
|
|
** fEquals: whether string must be terminated by an equals sign.
|
|
** Returns:
|
|
** fFalse for mismatch or bad format of option.
|
|
** fTrue otherwise.
|
|
**
|
|
**************************************************************************/
|
|
BOOL APIENTRY FMatchPrefix(PSZ psz,SZ szToMatch,BOOL fEquals)
|
|
{
|
|
AssertDataSeg();
|
|
|
|
ChkArg(psz != (PSZ)NULL &&
|
|
*psz != (SZ)NULL, 1, fFalse);
|
|
ChkArg(szToMatch != (SZ)NULL &&
|
|
*szToMatch >= 'A' &&
|
|
*szToMatch <= 'Z', 2, fFalse);
|
|
|
|
while (**psz != '\0' &&
|
|
**psz != '=' &&
|
|
!FWhiteSpaceChp(**psz) &&
|
|
*szToMatch != '\0')
|
|
{
|
|
if (**psz != *szToMatch)
|
|
return(fFalse);
|
|
(*psz)++;
|
|
szToMatch++;
|
|
}
|
|
|
|
if (fEquals)
|
|
{
|
|
if (**psz != '=')
|
|
return(fFalse);
|
|
else
|
|
(*psz)++;
|
|
}
|
|
else if (**psz != '\0')
|
|
return(fFalse);
|
|
|
|
return(fTrue);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Parses a string representation of a version into two unsigned
|
|
** long values - the most significant and the least significant.
|
|
** Arguments:
|
|
** szVer: non-Null SZ of the form "a,b,c,d" where each field is
|
|
** an unsigned word. Omitted fields are assumed to be the least
|
|
** significant (eg d then c then b then a) and are parsed as zeros.
|
|
** So "a,b" is equivalent to "a,b,0,0".
|
|
** pulMS: non-Null location to store the Most Significant long value
|
|
** built from a,b
|
|
** pulLS: non-Null location to store the Least Significant long value
|
|
** built from c,d
|
|
** Returns:
|
|
** fFalse if szVer is of a bad format.
|
|
** fTrue otherwise.
|
|
**
|
|
**************************************************************************/
|
|
BOOL APIENTRY FParseVersion(szVer, pulMS, pulLS)
|
|
SZ szVer;
|
|
PULONG pulMS;
|
|
PULONG pulLS;
|
|
{
|
|
USHORT rgus[4];
|
|
USHORT ius;
|
|
ULONG ulTmp;
|
|
|
|
AssertDataSeg();
|
|
|
|
ChkArg(szVer != (SZ)NULL, 1, fFalse);
|
|
ChkArg(pulMS != (PULONG)NULL, 2, fFalse);
|
|
ChkArg(pulLS != (PULONG)NULL, 3, fFalse);
|
|
|
|
*pulMS = *pulLS = 0L;
|
|
|
|
for (ius = 0; ius < 4; ius++) {
|
|
|
|
rgus[ius] = (USHORT) atoi(szVer);
|
|
|
|
while (*szVer != '\0' && *szVer != ',') {
|
|
if (!isdigit(*szVer++)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
|
|
if (*szVer == ',') {
|
|
szVer++;
|
|
}
|
|
}
|
|
|
|
ulTmp = rgus[0];
|
|
*pulMS = (ulTmp << 16) + rgus[1];
|
|
ulTmp = rgus[2];
|
|
*pulLS = (ulTmp << 16) + rgus[3];
|
|
|
|
return(fTrue);
|
|
|
|
|
|
// // no versioning in WIN32
|
|
// Unused(szVer);
|
|
// Unused(pulMS);
|
|
// Unused(pulLS);
|
|
// return(fTrue);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Handles one option field from a file description line.
|
|
** Arguments:
|
|
** poer: non-NULL valid OER to fill.
|
|
** iField: index of existing field to read.
|
|
** Notes:
|
|
** Requires that the current INF structure was initialized with a
|
|
** successful call to GrcOpenInf() and that the current Read location
|
|
** is valid.
|
|
** Returns:
|
|
** grcOkay for success.
|
|
** grcOutOfMemory for out of memory.
|
|
** grcINFBadFDLine for bad format.
|
|
** grcNotOkay otherwise.
|
|
**
|
|
**************************************************************************/
|
|
GRC APIENTRY GrcHandleSfdOption(INT Line,POER poer,UINT iField)
|
|
{
|
|
SZ sz, szCur;
|
|
GRC grc = grcOkay;
|
|
BOOL fNot = fFalse;
|
|
|
|
AssertDataSeg();
|
|
|
|
PreCondInfOpen(grcNotOkay);
|
|
|
|
ChkArg(poer != (POER)NULL, 1, grcNotOkay);
|
|
ChkArg(FValidPoer(poer), 1, grcNotOkay);
|
|
ChkArg(iField >= 1 && CFieldsInInfLine(Line) >= iField, 2, grcNotOkay);
|
|
|
|
if ((szCur = sz = SzGetNthFieldFromInfLine(Line,iField)) == (SZ)NULL)
|
|
return(grcOutOfMemory);
|
|
|
|
if (*szCur == '!')
|
|
{
|
|
fNot = fTrue;
|
|
szCur++;
|
|
}
|
|
|
|
switch (*szCur)
|
|
{
|
|
case 'A':
|
|
if (!FMatchPrefix(&szCur, "APPEND", !fNot))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->szAppend = (SZ)NULL;
|
|
else if ((poer->szAppend = SzDupl(szCur)) == (SZ)NULL)
|
|
grc = grcOutOfMemory;
|
|
else if (CchlValidSubPath(poer->szAppend) == (CCHP)0 ||
|
|
poer->szBackup != (SZ)NULL ||
|
|
poer->szRename != (SZ)NULL ||
|
|
(poer->oef & oefRoot) == oefRoot)
|
|
grc = grcINFBadFDLine;
|
|
break;
|
|
|
|
case 'B':
|
|
if (!FMatchPrefix(&szCur, "BACKUP", !fNot))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->szBackup = (SZ)NULL;
|
|
else if ((poer->szBackup = SzDupl(szCur)) == (SZ)NULL)
|
|
grc = grcOutOfMemory;
|
|
else if ((*(poer->szBackup) != '*' ||
|
|
*(poer->szBackup + 1) != '\0') &&
|
|
CchlValidSubPath(poer->szBackup) == (CCHP)0)
|
|
grc = grcINFBadFDLine;
|
|
else if (poer->szAppend != (SZ)NULL)
|
|
grc = grcINFBadFDLine;
|
|
break;
|
|
|
|
case 'C':
|
|
if (!FMatchPrefix(&szCur, "COPY", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->oef &= ~oefCopy;
|
|
else
|
|
poer->oef |= oefCopy;
|
|
break;
|
|
|
|
case 'D': /* Date, Decompress, Description */
|
|
if (*(szCur + 1) == 'A')
|
|
{
|
|
if (!FMatchPrefix(&szCur, "DATE", !fNot))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->szDate = (SZ)NULL;
|
|
else if ((poer->szDate = SzDupl(szCur)) == (SZ)NULL)
|
|
grc = grcOutOfMemory;
|
|
else if (!FValidOerDate(poer->szDate))
|
|
grc = grcINFBadFDLine;
|
|
}
|
|
else if (*(szCur + 1) == 'E')
|
|
{
|
|
if (*(szCur + 2) == 'C')
|
|
{
|
|
if (!FMatchPrefix(&szCur, "DECOMPRESS", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->oef &= ~oefDecompress;
|
|
else
|
|
poer->oef |= oefDecompress;
|
|
}
|
|
else if (*(szCur + 2) == 'S')
|
|
{
|
|
if (*(szCur + 3) == 'C')
|
|
{
|
|
if (!FMatchPrefix(&szCur, "DESCRIPTION", !fNot))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->szDescription = (SZ)NULL;
|
|
else if ((poer->szDescription = SzDupl(szCur)) == (SZ)NULL)
|
|
grc = grcOutOfMemory;
|
|
}
|
|
else if (*(szCur + 3) == 'T') /* REVIEW EBU */
|
|
{
|
|
if (!FMatchPrefix(&szCur, "DESTINATION", !fNot))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->szDest = (SZ)NULL;
|
|
else if ((poer->szDest = SzDupl(szCur)) == (SZ)NULL)
|
|
grc = grcOutOfMemory;
|
|
}
|
|
else
|
|
grc = grcINFBadFDLine;
|
|
}
|
|
else
|
|
grc = grcINFBadFDLine;
|
|
}
|
|
else
|
|
grc = grcINFBadFDLine;
|
|
break;
|
|
|
|
case 'N': /* NoDeleteSource, NoLog */
|
|
|
|
if(*(szCur + 1) == 'O') {
|
|
if(*(szCur + 2) == 'D') {
|
|
if(!FMatchPrefix(&szCur, "NODELETESOURCE", fFalse)) {
|
|
grc = grcINFBadFDLine;
|
|
} else if (fNot) {
|
|
poer->oef &= ~oefNoDeleteSource;
|
|
} else {
|
|
poer->oef |= oefNoDeleteSource;
|
|
}
|
|
} else if(*(szCur + 2) == 'L') {
|
|
if(!FMatchPrefix(&szCur, "NOLOG", fFalse)) {
|
|
grc = grcINFBadFDLine;
|
|
} else if (fNot) {
|
|
poer->oef &= ~oefNoLog;
|
|
} else {
|
|
poer->oef |= oefNoLog;
|
|
}
|
|
}
|
|
} else {
|
|
grc = grcINFBadFDLine;
|
|
}
|
|
break;
|
|
|
|
case 'O':
|
|
if (!FMatchPrefix(&szCur, "OVERWRITE", !fNot))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->owm = owmNever;
|
|
else
|
|
{
|
|
switch (*szCur)
|
|
{
|
|
case 'A':
|
|
if (!FMatchPrefix(&szCur, "ALWAYS", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
poer->owm = owmAlways;
|
|
break;
|
|
|
|
case 'N':
|
|
if (!FMatchPrefix(&szCur, "NEVER", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
poer->owm = owmNever;
|
|
break;
|
|
|
|
case 'O':
|
|
if (!FMatchPrefix(&szCur, "OLDER", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
poer->owm = owmOlder;
|
|
break;
|
|
|
|
case 'V':
|
|
if (!FMatchPrefix(&szCur, "VERIFYSOURCEOLDER", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
poer->owm = owmVerifySourceOlder;
|
|
break;
|
|
|
|
case 'U':
|
|
if (!FMatchPrefix(&szCur, "UNPROTECTED", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
poer->owm = owmUnprotected;
|
|
break;
|
|
|
|
default:
|
|
grc = grcINFBadFDLine;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'R': /* ReadOnly, Rename, Root */
|
|
if (*(szCur + 1) == 'E')
|
|
{
|
|
if (*(szCur + 2) == 'A')
|
|
{
|
|
if (!FMatchPrefix(&szCur, "READONLY", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->oef &= ~oefReadOnly;
|
|
else
|
|
poer->oef |= oefReadOnly;
|
|
}
|
|
else if (*(szCur + 2) == 'N')
|
|
{
|
|
if (!FMatchPrefix(&szCur, "RENAME", !fNot))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->szRename = (SZ)NULL;
|
|
else if ((poer->szRename = SzDupl(szCur)) == (SZ)NULL)
|
|
grc = grcOutOfMemory;
|
|
else if (CchlValidSubPath(poer->szRename) == (CCHP)0 ||
|
|
poer->szAppend != (SZ)NULL ||
|
|
(poer->oef & oefRoot) == oefRoot)
|
|
grc = grcINFBadFDLine;
|
|
}
|
|
else
|
|
grc = grcINFBadFDLine;
|
|
}
|
|
else if (*(szCur + 1) == 'O')
|
|
{
|
|
if (!FMatchPrefix(&szCur, "ROOT", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->oef &= ~oefRoot;
|
|
else if (poer->szAppend != (SZ)NULL ||
|
|
poer->szRename != (SZ)NULL)
|
|
grc = grcINFBadFDLine;
|
|
else
|
|
poer->oef |= oefRoot;
|
|
}
|
|
else
|
|
grc = grcINFBadFDLine;
|
|
break;
|
|
|
|
case 'S': /* SetTimeStamp, Size */
|
|
if (*(szCur + 1) == 'E')
|
|
{
|
|
if (!FMatchPrefix(&szCur, "SETTIMESTAMP", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->oef &= ~oefTimeStamp;
|
|
else
|
|
poer->oef |= oefTimeStamp;
|
|
}
|
|
else if (*(szCur + 1) == 'I')
|
|
{
|
|
if (!FMatchPrefix(&szCur, "SIZE", !fNot))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->lSize = 0L;
|
|
else if ((poer->lSize = ((LONG)atol(szCur) / 100 )) < 0L)
|
|
grc = grcINFBadFDLine;
|
|
else
|
|
poer->lSize = poer->lSize + 1; // make size atleast one
|
|
}
|
|
else
|
|
grc = grcINFBadFDLine;
|
|
break;
|
|
|
|
case 'T':
|
|
if (!FMatchPrefix(&szCur, "TIME", !fNot))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->ctuCopyTime = (CTU)0;
|
|
else
|
|
{
|
|
LONG l = (LONG)atol(szCur);
|
|
|
|
if (l < 0L)
|
|
grc = grcINFBadFDLine;
|
|
else
|
|
poer->ctuCopyTime = (CTU)l;
|
|
}
|
|
break;
|
|
|
|
case 'U':
|
|
if (FMatchPrefix(&szCur, "UNDO", fFalse)) {
|
|
if (fNot) {
|
|
poer->oef &= ~oefUndo;
|
|
}
|
|
else {
|
|
poer->oef |= oefUndo;
|
|
}
|
|
}
|
|
else if (FMatchPrefix(&szCur, "UPGRADEONLY", fFalse)) {
|
|
if (fNot) {
|
|
poer->oef &= ~oefUpgradeOnly;
|
|
}
|
|
else {
|
|
poer->oef |= oefUpgradeOnly;
|
|
}
|
|
}
|
|
else {
|
|
grc = grcINFBadFDLine;
|
|
}
|
|
break;
|
|
|
|
case 'V': /* Version, Vital */
|
|
if (*(szCur + 1) == 'E')
|
|
{
|
|
if (!FMatchPrefix(&szCur, "VERSION", !fNot))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
{
|
|
poer->ulVerMS = 0L;
|
|
poer->ulVerLS = 0L;
|
|
}
|
|
else if (!FParseVersion(szCur, &(poer->ulVerMS), &(poer->ulVerLS)))
|
|
grc = grcINFBadFDLine;
|
|
}
|
|
else if (*(szCur + 1) == 'I')
|
|
{
|
|
if (!FMatchPrefix(&szCur, "VITAL", fFalse))
|
|
grc = grcINFBadFDLine;
|
|
else if (fNot)
|
|
poer->oef &= ~oefVital;
|
|
else
|
|
poer->oef |= oefVital;
|
|
}
|
|
else
|
|
grc = grcINFBadFDLine;
|
|
break;
|
|
|
|
default:
|
|
grc = grcINFBadFDLine;
|
|
}
|
|
|
|
SFree(sz);
|
|
Assert(grc != grcOkay || FValidPoer(poer));
|
|
|
|
return(grc);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Allocates a new Section File Descriptor and fills it by reading and
|
|
** parsing the given INF read line.
|
|
** Arguments:
|
|
** ppsfd: non-Null location to store PSFD if successful.
|
|
** poer: non-Null valid filled OER pointer.
|
|
** Notes:
|
|
** Requires that the current INF structure was initialized with a
|
|
** successful call to GrcOpenInf().
|
|
** Returns:
|
|
** grcOkay if successful.
|
|
** grcOutOfMemory if out of memory.
|
|
** grcINFBadFDLine if the current line has a bad format.
|
|
** grcNotOkay otherwise.
|
|
**
|
|
**************************************************************************/
|
|
GRC APIENTRY GrcGetSectionFileLine(INT Line,PPSFD ppsfd,POER poer)
|
|
{
|
|
PSFD psfd;
|
|
UINT cFields, iField;
|
|
SZ sz;
|
|
|
|
AssertDataSeg();
|
|
|
|
PreCondInfOpen(grcNotOkay);
|
|
|
|
ChkArg(ppsfd != (PPSFD)NULL, 1, grcNotOkay);
|
|
ChkArg(poer != (POER)NULL, 2, grcNotOkay);
|
|
ChkArg(FValidPoer(poer), 2, grcNotOkay);
|
|
|
|
*ppsfd = (PSFD)NULL;
|
|
|
|
if ((cFields = CFieldsInInfLine(Line)) < 2)
|
|
return(grcINFBadFDLine);
|
|
|
|
if ((psfd = PsfdAlloc()) == (PSFD)NULL)
|
|
return(grcOutOfMemory);
|
|
|
|
if ((sz = SzGetNthFieldFromInfLine(Line,1)) == (SZ)NULL)
|
|
{
|
|
EvalAssert(FFreePsfd(psfd));
|
|
return(grcOutOfMemory);
|
|
}
|
|
|
|
if ((psfd->did = (DID)atoi(sz)) < didMin ||
|
|
psfd->did > didMost)
|
|
{
|
|
SFree(sz);
|
|
EvalAssert(FFreePsfd(psfd));
|
|
return(grcINFBadFDLine);
|
|
}
|
|
|
|
psfd->InfId = pLocalInfPermInfo()->InfId;
|
|
|
|
SFree(sz);
|
|
|
|
if ((psfd->szFile = SzGetNthFieldFromInfLine(Line,2)) == (SZ)NULL)
|
|
{
|
|
EvalAssert(FFreePsfd(psfd));
|
|
return(grcOutOfMemory);
|
|
}
|
|
|
|
if (CchlValidSubPath(psfd->szFile) == (CCHP)0)
|
|
{
|
|
EvalAssert(FFreePsfd(psfd));
|
|
return(grcINFBadFDLine);
|
|
}
|
|
|
|
psfd->oer = *poer;
|
|
|
|
for (iField = 3; iField <= cFields; iField++)
|
|
{
|
|
GRC grc;
|
|
|
|
if ((grc = GrcHandleSfdOption(Line, &(psfd->oer), iField)) != grcOkay)
|
|
{
|
|
/* REVIEW - could just reset all and leave a few strings! */
|
|
if ((psfd->oer).szAppend == poer->szAppend)
|
|
(psfd->oer).szAppend = (SZ)NULL;
|
|
if ((psfd->oer).szBackup == poer->szBackup)
|
|
(psfd->oer).szBackup = (SZ)NULL;
|
|
if ((psfd->oer).szDate == poer->szDate)
|
|
(psfd->oer).szDate = (SZ)NULL;
|
|
if ((psfd->oer).szDescription == poer->szDescription)
|
|
(psfd->oer).szDescription = (SZ)NULL;
|
|
if ((psfd->oer).szDest == poer->szDest) /* REVIEW EBU */
|
|
(psfd->oer).szDest = (SZ)NULL;
|
|
if ((psfd->oer).szRename == poer->szRename)
|
|
(psfd->oer).szRename = (SZ)NULL;
|
|
EvalAssert(FFreePsfd(psfd));
|
|
return(grc);
|
|
}
|
|
}
|
|
|
|
AssertRet(FValidPsfd(psfd), grcNotOkay);
|
|
|
|
*ppsfd = psfd;
|
|
|
|
return(grcOkay);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Determines if the given INF line is a list-include statement of
|
|
** the form: [ <Key> = ] @( <Section> ) [, @( <Key> ) ]
|
|
** Arguments:
|
|
** none
|
|
** Notes:
|
|
** Requires that the current INF structure was initialized with a
|
|
** successful call to GrcOpenInf() and that the current Read location
|
|
** is valid.
|
|
** Returns:
|
|
** fTrue if current INF line conforms to above format.
|
|
** fFalse if it does not.
|
|
**
|
|
**************************************************************************/
|
|
BOOL APIENTRY FListIncludeStatementLine(INT Line)
|
|
{
|
|
UINT cFields;
|
|
SZ sz, szLast;
|
|
|
|
AssertDataSeg();
|
|
|
|
PreCondInfOpen(fFalse);
|
|
|
|
if ((cFields = CFieldsInInfLine(Line)) < 1 ||
|
|
cFields > 2 ||
|
|
(sz = SzGetNthFieldFromInfLine(Line,1)) == (SZ)NULL)
|
|
return(fFalse);
|
|
|
|
if (*sz != '@' ||
|
|
*(sz + 1) != '(' ||
|
|
(szLast = SzLastChar(sz)) == (SZ)NULL ||
|
|
*szLast != ')')
|
|
goto L_FLISL_ERROR;
|
|
|
|
SFree(sz);
|
|
|
|
if (cFields == 1)
|
|
return(fTrue);
|
|
|
|
if ((sz = SzGetNthFieldFromInfLine(Line,2)) == (SZ)NULL)
|
|
return(fFalse);
|
|
|
|
if (*sz != '@' ||
|
|
*(sz + 1) != '(' ||
|
|
(szLast = SzLastChar(sz)) == (SZ)NULL ||
|
|
*szLast != ')')
|
|
goto L_FLISL_ERROR;
|
|
|
|
SFree(sz);
|
|
|
|
return(fTrue);
|
|
|
|
L_FLISL_ERROR:
|
|
if (sz != (SZ)NULL)
|
|
SFree(sz);
|
|
|
|
return(fFalse);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Parses a list-include-statement from an INF file description section.
|
|
** Arguments:
|
|
** pszSection: non-Null pointer to a currently Null string which this
|
|
** routine will replace with a pointer to an allocated buffer
|
|
** containing the section name on the line.
|
|
** pszKey: non-Null pointer to a currently Null string which this
|
|
** routine will replace with a pointer to an allocated buffer
|
|
** containing the key name on the line if one exists.
|
|
** Notes:
|
|
** Requires that the current INF structure was initialized with a
|
|
** successful call to GrcOpenInf() and that the current Read location
|
|
** is valid and that it points to a valid list-include statement.
|
|
** Returns:
|
|
** grcOkay if successful.
|
|
** grcOutOfMemory if out of memory.
|
|
** grcNotOkay otherwise.
|
|
**
|
|
**************************************************************************/
|
|
GRC APIENTRY GrcGetListIncludeSectionLine(INT Line,
|
|
PSZ pszSection,
|
|
PSZ pszKey)
|
|
{
|
|
UINT cFields;
|
|
SZ sz, szLast;
|
|
|
|
AssertDataSeg();
|
|
|
|
PreCondInfOpen(grcNotOkay);
|
|
PreCondition(FListIncludeStatementLine(Line), grcNotOkay);
|
|
|
|
ChkArg(pszSection != (PSZ)NULL && *pszSection == (SZ)NULL, 1, grcNotOkay);
|
|
ChkArg(pszKey != (PSZ)NULL && *pszKey == (SZ)NULL, 2, grcNotOkay);
|
|
|
|
EvalAssert((cFields = CFieldsInInfLine(Line)) == 1 || cFields == 2);
|
|
if ((sz = SzGetNthFieldFromInfLine(Line,1)) == (SZ)NULL)
|
|
return(grcOutOfMemory);
|
|
|
|
Assert(*sz == '@' && *(sz + 1) == '(');
|
|
EvalAssert((szLast = SzLastChar(sz)) != (SZ)NULL);
|
|
Assert(*szLast == ')');
|
|
|
|
*szLast = '\0';
|
|
*pszSection = SzDupl(sz + 2);
|
|
*szLast = ')';
|
|
|
|
if (*pszSection == (SZ)NULL)
|
|
goto L_GGLISL_ERROR;
|
|
|
|
SFree(sz);
|
|
sz = (SZ)NULL;
|
|
|
|
if (cFields == 1)
|
|
return(grcOkay);
|
|
|
|
Assert(cFields == 2);
|
|
if ((sz = SzGetNthFieldFromInfLine(Line,2)) == (SZ)NULL)
|
|
goto L_GGLISL_ERROR;
|
|
|
|
Assert(*sz == '@' && *(sz + 1) == '(');
|
|
EvalAssert((szLast = SzLastChar(sz)) != (SZ)NULL);
|
|
Assert(*szLast == ')');
|
|
|
|
*szLast = '\0';
|
|
*pszKey = SzDupl(sz + 2);
|
|
*szLast = ')';
|
|
|
|
if (*pszKey == (SZ)NULL)
|
|
goto L_GGLISL_ERROR;
|
|
|
|
SFree(sz);
|
|
|
|
return(grcOkay);
|
|
|
|
L_GGLISL_ERROR:
|
|
if (sz != (SZ)NULL)
|
|
SFree(sz);
|
|
if (*pszSection != (SZ)NULL)
|
|
SFree(*pszSection);
|
|
if (*pszKey != (SZ)NULL)
|
|
SFree(*pszKey);
|
|
|
|
return(grcOutOfMemory);
|
|
}
|