Microsoft-3D-Movie-Maker/SETUP/CUSTDLL/SRC/PARSECA.C
2022-05-03 16:31:19 -07:00

567 lines
12 KiB
C

/* Copyright (c) Microsoft Corporation.
Licensed under the MIT License. */
/***************************************************************************
**
** File: PARSECA.C
** Purpose: Custom Action data parsing routines
** for the Sample App DLL.
** Notes:
**
****************************************************************************/
#define PARSECA_C
#include "stdinc.h"
#include <stdlib.h> /* _MAX_PATH */
#include <ctype.h> /* isdigit */
#include "setupapi.h"
#include "cui.h"
#include "stdtypes.h"
#include "setupkit.h"
#include "datadef.h"
#include "parseca.h"
#include "sampcacb.h"
/* REVIEW: Put the strings in sampsz.h.
*/
#define STR_BADSECT_ERR "InstallWinPermFile Object: Bad INF Section data value"
#define STR_BADKEY_ERR "InstallWinPermFile Object: Bad INF Key data value"
#define STR_XTRADATA_ERR "InstallWinPermFile Object: extra unrecognized data values"
#define STR_PARSE_ERR "Setup Parse Error in Initialize pass"
#define STR_OBJID "Object ID %d: %s."
#define STR_MISSING_ERR "SingSelListDlg Object: Missing data value"
#define STR_BADDATA_ERR "SingSelListDlg Object: Bad data value"
#define STR_OBJID_ERR "Syntax Error in List of Obj IDs"
const CHAR chFieldSep = chTab;
#define FWhiteSpaceCh(ch) ((BOOL)((ch) == chSpace || (ch) == chTab))
#define chLorSep chComma
/*
****************************************************************************/
RC PUBLIC RcParseInfSectKey ( OR orCur, SZ szData, PSZ pszInfSect,
PSZ pszInfKey )
{
Assert(szData != szNull);
Assert(pszInfSect != pszNull);
Assert(pszInfKey != pszNull);
if (*pszInfSect != szNull) /* Already parsed and alloc'ed? */
return (rcOk);
if (!FReadDataFieldString(&szData, pszInfSect))
return (rcFail);
Assert(*pszInfSect != szNull);
if (!FValidInfSection(*pszInfSect) || !DoesInfSectionExist(*pszInfSect))
{
ParseError(orCur, STR_BADSECT_ERR);
return (rcFail);
}
if (!FReadDataFieldString(&szData, pszInfKey))
return (rcFail);
Assert(*pszInfKey != szNull);
if (!FValidInfKey(*pszInfKey)
|| !DoesInfSectionKeyExist(*pszInfSect, *pszInfKey))
{
ParseError(orCur, STR_BADKEY_ERR);
return (rcFail);
}
if (*szData != chEos)
{
ParseError(orCur, STR_XTRADATA_ERR);
return (rcFail);
}
return (rcOk);
}
/*
************************************************************************/
RC PUBLIC RcParseLor ( PCD pcd, OR orCur, SZ szData, PPLOR pplor )
{
Assert(pcd != lpvoidNull);
Assert(FValidOr(pcd, orCur));
Assert(szData != szNull);
Assert(pplor != pplorNull);
if (*pplor != plorNull)
return (rcOk);
while (FWhiteSpaceCh(*szData))
szData = SzNextChar(szData);
if (*szData == chEos)
{
ParseError(orCur, STR_MISSING_ERR);
return (rcFail);
}
/* OOM or non-digit chars msg handled inside PlorFromSz()
*/
if ((*pplor = PlorFromSz(orCur, szData)) == plorNull)
return (rcFail);
if (!FValidGroupPlor(pcd, *pplor, orCur))
{
FFreePlor(pplor);
ParseError(orCur, STR_BADDATA_ERR);
return (rcFail);
}
return (rcOk);
}
/*
************************************************************************/
BOOL PUBLIC FReadDataFieldString ( PSZ pszData, PSZ pszMember )
{
CHAR rgch[cchSzMax];
Assert(pszData != pszNull);
Assert(*pszData != szNull);
Assert(pszMember != pszNull);
*pszData = SzGetTableField(*pszData, rgch, cchSzMax, chComma);
if (*pszData == szNull)
return (fFalse);
if ((*pszMember = SzStrDupl(rgch)) == szNull)
return (fFalse);
return (fTrue);
}
/*
** Purpose:
** Duplicates a string.
** Arguments:
** sz: string to duplicate.
** Returns:
** duplicated string if successful, szNull if not.
** Notes:
****************************************************************************/
SZ PUBLIC SzStrDupl ( SZ sz )
{
SZ szNew;
Assert(sz != szNull);
while ((szNew = (SZ)PbAlloc(CbStrLen(sz) + 1)) == szNull)
{
if (!FHandleOOM())
return (szNull);
}
SzStrCopy(szNew, sz);
return (szNew);
}
/*
** Purpose:
** Determine if a string is a valid Inf section.
** Arguments:
** szSection: The section.
** Returns:
** fTrue if the string is valid, fFalse otherwise.
** Notes:
**
****************************************************************************/
BOOL PUBLIC FValidInfSection ( SZ szSection )
{
SZ szLast;
if (FEmptySz(szSection))
return (fFalse);
if (*szSection == chSpace)
return (fFalse);
szLast = szSection;
while (*szSection != chEos)
{
if (*szSection == chRgtSqBracket)
return (fFalse);
szLast = szSection;
szSection = SzNextChar(szSection);
}
if (*szLast == chSpace)
return (fFalse);
return (fTrue);
}
/*
** Purpose:
** Determine if a string is a valid Inf key.
** Arguments:
** szKey: The key.
** Returns:
** fTrue if the string is valid, fFalse otherwise.
** Notes:
**
****************************************************************************/
BOOL PUBLIC FValidInfKey ( SZ szKey )
{
SZ szLast;
if (FEmptySz(szKey))
return (fFalse);
if (*szKey == chSpace || *szKey == chLftSqBracket)
return (fFalse);
szLast = szKey;
while (*szKey != chEos)
{
if (*szKey == chEquals)
return (fFalse);
szLast = szKey;
szKey = SzNextChar(szKey);
}
if (*szLast == chSpace)
return (fFalse);
return (fTrue);
}
/*
** Notes
** Each OR in the PLOR must be greater than the group OR (which
** implicitly is greater than orNil). This prevents circular
** references and makes processing easier since it can run top
** to bottom.
************************************************************************/
BOOL PUBLIC FValidGroupPlor ( PCD pcd, PLOR plor, OR orGroup )
{
UINT ior;
Assert(plor != plorNull);
Assert(plor->cor > 0);
Assert(plor->rgor != rgorNull);
Assert(orGroup != orNil);
for (ior = 0; ior < plor->cor; ior++)
{
OR or = plor->rgor[ior];
UINT iorT;
if (or <= orGroup
|| or >= pcd->cObjectsMax
|| PodGetObjData(pcd, or) == podNull)
{
return (fFalse);
}
for (iorT = ior + 1; iorT < plor->cor; iorT++)
{
if (or == plor->rgor[iorT])
return (fFalse);
}
}
return (fTrue);
}
/*
** Purpose:
** Show a Message Box with the appropriate info.
** Arguments:
** or: object reference number.
** szcMsg: The error message.
** Returns:
** none.
** Notes:
**
****************************************************************************/
VOID PUBLIC ParseError ( OR or, SZ szMsg )
{
CHAR rgchText[2*cchSzMax];
Assert(CbStrLen(STR_OBJID) + 5 + CbStrLen(szMsg) < sizeof rgchText);
wsprintf(rgchText, STR_OBJID, or, szMsg);
DoMsgBox(rgchText, STR_PARSE_ERR, MB_OK | MB_ICONEXCLAMATION);
}
/*
** Purpose:
** Extract the first field in szLine.
** Arguments:
** szLine: The buffer to parse for a field.
** szField: The buffer to receive the field.
** cbFieldMax: The size of the output buffer.
** chSep: The separator character.
** Returns:
** A pointer to the start of the next field in szLine.
** szNull if an error was detected.
** Notes:
**
****************************************************************************/
SZ PUBLIC SzGetTableField ( SZ szLine, SZ szField, CB cbFieldMax,
CHAR chSep )
{
BOOL fQuotedField = fFalse;
BOOL fInQuotedField = fFalse;
CB cbFieldMaxCur = cbFieldMax;
SZ szFieldEnd = szField;
#ifdef DEBUG
SZ szLineStart = szLine;
SZ szFieldStart = szField;
#endif
Assert(szLine != szNull);
Assert(szField != szNull);
Assert(cbFieldMax > 0);
*szField = chEos;
cbFieldMaxCur--;
Assert(chSep != chSpace);
while (FWhiteSpaceCh(*szLine) && *szLine != chSep)
szLine = SzNextChar(szLine);
if (*szLine == chDblQuote) /* Strip off the outermost set of quotes. */
{
fQuotedField = fTrue;
fInQuotedField = fTrue;
szLine = SzNextChar(szLine);
}
while (*szLine != chEos && (fInQuotedField || *szLine != chSep))
{
BOOL fNonSpace;
if (*szLine == chDblQuote)
{
if (!fInQuotedField)
{
if (chSep == chFieldSep) /* in XL tab file only */
{
DebugMsgBox(szLineStart, "Badly formed field: Quote in "
"unquoted field");
return (szNull);
}
}
else
{
szLine = SzNextChar(szLine);
if (*szLine == chSep || *szLine == chEos)
{
fInQuotedField = fFalse;
break;
}
/* Consecutive double quotes are treated as one quote. */
if (*szLine != chDblQuote)
{
/* Strip off trailing spaces
*/
while (FWhiteSpaceCh(*szLine) && *szLine != chSep)
szLine = SzNextChar(szLine);
if (*szLine == chSep || *szLine == chEos)
{
fInQuotedField = fFalse;
break;
}
DebugMsgBox(szLineStart, "Badly formed field: "
"Non-doubled quote in quoted field");
return (szNull);
}
}
}
if (cbFieldMaxCur == 0)
{
#ifdef DEBUG
CHAR rgch[cchSzMax];
wsprintf(rgch, "Error: Field is too long (>= %d)", cbFieldMax);
DebugMsgBox(szLineStart, rgch);
#endif
*szField = chEos;
return (szNull);
}
fNonSpace = (*szLine != chSpace);
CopyCharToBuf(&szLine, &szField, &cbFieldMaxCur);
if (fNonSpace)
szFieldEnd = szField;
}
if (!fQuotedField)
szField = szFieldEnd; /* Strip off trailing spaces */
*szField = chEos;
if (fInQuotedField)
{
DebugMsgBox(szLineStart, "Badly formed field: Unmatched quote");
return (szNull);
}
Assert(*szLine == chEos || *szLine == chSep);
if (*szLine == chSep)
szLine = SzNextChar(szLine);
return (szLine);
}
/*
** Purpose:
** Copies a character from one buffer to another and advancing pointers.
** Arguments:
** pszCur: Pointer to string to copy character from.
** pszBuf: Pointer to string to copy character to.
** pcbBuf: Pointer to useable size of pszBuf.
** Returns:
** none.
** Notes:
**
****************************************************************************/
VOID PUBLIC CopyCharToBuf ( PSZ pszCur, PSZ pszBuf, PCB pcbBuf )
{
SZ szEnd = SzNextChar(*pszCur);
if ((CB)(szEnd - *pszCur) <= *pcbBuf)
{
while (*pszCur < szEnd)
{
*(*pszBuf)++ = *(*pszCur)++;
(*pcbBuf)--;
}
}
else
{
*pszCur = szEnd;
*pcbBuf = 0;
}
}
/*
************************************************************************/
PLOR PUBLIC PlorFromSz ( OR orCur, SZ sz )
{
PLOR plor = plorNull;
SZ szCur;
UINT cor;
Assert(sz != szNull);
LWalkStringReadingLOR:
szCur = sz;
cor = 0;
while (*szCur != chEos)
{
SZ szSep;
while (FWhiteSpaceCh(*szCur))
szCur = SzNextChar(szCur);
if (*szCur == chEos)
break;
szSep = szCur;
while (*szSep != chEos
&& !FWhiteSpaceCh(*szSep)
&& *szSep != chLorSep)
{
if (!isdigit(*szSep))
{
ParseError(orCur, STR_OBJID_ERR);
FFreePlor(&plor);
return (plorNull);
}
szSep = SzNextChar(szSep);
}
if (plor != plorNull)
{
CHAR chSav;
Assert(plor->rgor != rgorNull);
chSav = *szSep;
*szSep = chEos;
plor->rgor[cor] = atoi(szCur);
*szSep = chSav;
}
cor++;
szCur = szSep;
if (*szCur != chEos)
szCur = SzNextChar(szCur);
}
if (plor == plorNull
&& cor > 0
&& (plor = PlorAlloc(cor)) != plorNull)
{
Assert(plor->rgor != rgorNull);
Assert(plor->cor == cor);
goto LWalkStringReadingLOR;
}
return (plor);
}
/*
************************************************************************/
BOOL PUBLIC FFreePlor ( PPLOR pplor )
{
PLOR plor = *pplor;
if (plor != plorNull)
{
Assert(plor->cor > 0);
Assert(plor->rgor != rgorNull);
FFree((PB)(plor->rgor), (CB)(plor->cor * sizeof(OR)));
FFree((PB)plor, (CB)sizeof(LOR));
*pplor = plorNull;
}
return (fTrue);
}
/*
************************************************************************/
PLOR PUBLIC PlorAlloc ( UINT cor )
{
PLOR plor;
Assert(cor > 0);
while ((plor = (PLOR)PbAlloc((CB)sizeof(LOR))) == plorNull)
{
if (!FHandleOOM())
return (plorNull);
}
plor->cor = cor;
while ((plor->rgor = (RGOR)PbAlloc((CB)(cor * sizeof(OR)))) == rgorNull)
{
if (!FHandleOOM())
{
FFree((PB)plor, (CB)sizeof(LOR));
return (plorNull);
}
}
return (plor);
}