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.
230 lines
8.3 KiB
230 lines
8.3 KiB
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <strsafe.h>
|
|
|
|
#define BINPLACE_MAX_FULL_PATH 4096 // must match value in binplace.c
|
|
extern BOOL fVerbose; // imported from binplace.c
|
|
BOOL
|
|
PlaceFileMatch(
|
|
IN LPCSTR FullFileName,
|
|
IN OUT LPSTR PlaceFileEntry, // May be modified by env. var expansion
|
|
OUT LPSTR PlaceFileClass, // assumed CHAR[BINPLACE_MAX_FULL_PATH]
|
|
OUT LPSTR *PlaceFileNewName
|
|
)
|
|
// Returns TRUE if the filename matches the placefile entry.
|
|
// On TRUE return, PlaceFileNewName points to location within
|
|
// PlaceFileEntry. On FALSE return, PlaceFileClass and PlaceFileNewName are undefined.
|
|
{
|
|
const CHAR *pchEntryOrig; // Point to current parse pos of PlaceFileEntry
|
|
|
|
CHAR szEntryExp[BINPLACE_MAX_FULL_PATH]; // Holds fileEntry after environment expansion
|
|
PCHAR pchEntryExp, pchEntryExpEnd; // Point to current pos and end of EntryExp
|
|
PCHAR pchVarStart; // Points into EntryExp: where an env. expansion should start replacing
|
|
|
|
LPCSTR pszEnvVar;
|
|
|
|
const CHAR *pchEntryFnEnd; // Stores the end of the filename
|
|
const CHAR *pchFn; // Stores the current position within the filename
|
|
PCHAR pch;
|
|
PCHAR pchClass; // Current position within PlaceFileClass
|
|
|
|
// Check for early-exit opportunities
|
|
if(
|
|
!PlaceFileEntry ||
|
|
!FullFileName ||
|
|
!PlaceFileClass ||
|
|
PlaceFileEntry[0]==';' || // It is a full-line comment
|
|
PlaceFileEntry[0]=='\0' // Blank line
|
|
) {
|
|
return FALSE;
|
|
}
|
|
|
|
// ***
|
|
// *** Expand any environment variables in PlaceFileEntry (result goes back into PlaceFileEntry)
|
|
// ***
|
|
|
|
pchEntryExp = szEntryExp;
|
|
pchEntryExpEnd = pchEntryExp + (sizeof(szEntryExp)/sizeof(szEntryExp[0])) - 1;
|
|
pchVarStart = NULL; // Indicates that I haven't passed the starting % of an env. var.
|
|
|
|
// Skip over leading whitespace
|
|
for(
|
|
pchEntryOrig = PlaceFileEntry;
|
|
*pchEntryOrig==' ' || *pchEntryOrig=='\t';
|
|
pchEntryOrig++
|
|
)
|
|
{}
|
|
|
|
// StrCopy with environment variable replacement
|
|
while(*pchEntryOrig && pchEntryExp<pchEntryExpEnd) {
|
|
if(*pchEntryOrig == '%') {
|
|
if(pchVarStart) { // If this is a closing %
|
|
*pchEntryExp = 0; // Make sure the env. var. is null-terminated
|
|
|
|
// pchVarStart points to first %
|
|
if(pszEnvVar = getenv(pchVarStart + 1)) { // If the env. var is valid
|
|
// Copy it over
|
|
StringCchCopyEx(
|
|
pchVarStart, // Start where the first % was copied to
|
|
pchEntryExpEnd - pchVarStart, // Remaining = end - curPos
|
|
pszEnvVar,
|
|
&pchEntryExp,
|
|
NULL, // Don't need chars remaining
|
|
0 // No special flags
|
|
);
|
|
}
|
|
else // Environment variable not defined
|
|
{
|
|
pchEntryExp = pchVarStart; // Back up to opening %
|
|
// This effectively expands the undefined variable to ""
|
|
}
|
|
pchVarStart = NULL; // Reset to "unstarted"
|
|
pchEntryOrig++; // Skip past %
|
|
continue;
|
|
} else {
|
|
// This is an opening % - remember it, then continue copying in case
|
|
// they never close it.
|
|
pchVarStart = pchEntryExp;
|
|
}
|
|
}
|
|
*pchEntryExp++ = *pchEntryOrig++; // Unless we "continue", we copy the next char.
|
|
}
|
|
|
|
// NULL terminate expanded string
|
|
*pchEntryExp = 0;
|
|
|
|
// Copy result back
|
|
StringCchCopy(PlaceFileEntry, BINPLACE_MAX_FULL_PATH, szEntryExp);
|
|
|
|
// Chop off comment, if any
|
|
if(pch = strchr(PlaceFileEntry,';'))
|
|
*pch = 0;
|
|
|
|
// Chop off newline, if any
|
|
if(pch = strchr(PlaceFileEntry,'\n'))
|
|
*pch = 0;
|
|
|
|
// PlaceFileEntry now:
|
|
// - Has no leading whitespace
|
|
// - Has no comments (;)
|
|
// - All environment variables (%VARNAME%) have been expanded.
|
|
// - May have been truncated if the environment variables were really long!
|
|
|
|
// ***
|
|
// *** Determine if this is a match
|
|
// ***
|
|
|
|
// Scan for end of filename (next whitespace OR !)
|
|
for(
|
|
pchEntryOrig = PlaceFileEntry;
|
|
*pchEntryOrig!=0 && *pchEntryOrig!=' ' && *pchEntryOrig!='\t' && *pchEntryOrig!='!';
|
|
pchEntryOrig++
|
|
)
|
|
{}
|
|
|
|
if(*pchEntryOrig!=' ' && *pchEntryOrig!='\t') { // No class name specified
|
|
return FALSE;
|
|
}
|
|
|
|
pchEntryFnEnd = pchEntryOrig; // Save end of filename for later
|
|
|
|
pchFn = FullFileName + strlen(FullFileName);
|
|
|
|
// Scan backwards over filename and path
|
|
while(pchEntryOrig>PlaceFileEntry && pchFn > FullFileName)
|
|
{
|
|
pchEntryOrig--;
|
|
pchFn--;
|
|
|
|
if('*' == *pchEntryOrig) { // Wildcard for this portion
|
|
if(*(pchEntryOrig+1)!='\\' && *(pchEntryOrig+1)!='/') { // Invalid: "dir\*abc\filename"
|
|
// This also catches the invalid "dir\*" (wildcard invalid for filename).
|
|
if (fVerbose) {
|
|
fprintf( stdout, "BINPLACE : warning BNP0000: No wildcard in filename or mixed wildcard/text in class name: \"%s\"\n", PlaceFileEntry ) ;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
pchEntryOrig--; // Skip over the *
|
|
|
|
if(
|
|
pchEntryOrig <= PlaceFileEntry || // Can't start with wildcard ("*\dir\filename").
|
|
('\\'!=*pchEntryOrig && '/'!=*pchEntryOrig) // No partial wildcard ("dir\abc*\filename").
|
|
) {
|
|
if (fVerbose) {
|
|
fprintf( stdout, "BINPLACE : warning BNP0000: No wildcard at start of path or mixed wildcard/text in class name: \"%s\"\n", PlaceFileEntry ) ;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
while(pchFn > FullFileName && *pchFn != '\\' && *pchFn != '/') // Skip wildcarded directory name
|
|
pchFn--;
|
|
|
|
// Both pchFn and pchEntryOrig are now on a slash.
|
|
} else {
|
|
if(toupper(*pchFn) != toupper(*pchEntryOrig)) {
|
|
if( // Mismatch ok only on forward/backward slashes.
|
|
!(*pchFn == '/' || *pchFn == '\\') ||
|
|
!(*pchEntryOrig == '/' || *pchEntryOrig == '\\')
|
|
)
|
|
{
|
|
return FALSE; // Names don't match - exit
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Did we match? Conditions to be met:
|
|
// pchEntryOrig==PlaceFileEntry (match pattern completely consumed)
|
|
// pchFn==FullFileName (full file name completely consumed, perverse case) OR *pchFn==slash (normal case).
|
|
if(
|
|
pchEntryOrig != PlaceFileEntry ||
|
|
(pchFn != FullFileName && *(pchFn-1) !='/' && *(pchFn-1) != '\\')
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// ***
|
|
// *** Its a match. Set output variables accordingly.
|
|
// ***
|
|
|
|
// Skip to next whitespace (to skip over NewName, if present).
|
|
for(
|
|
pchEntryOrig = pchEntryFnEnd; // This is 1 past the end of the filename (saved previously)
|
|
*pchEntryOrig!=0 && *pchEntryOrig!=' ' && *pchEntryOrig!='\t';
|
|
pchEntryOrig++
|
|
)
|
|
{}
|
|
|
|
// Skip over whitespace before the class name
|
|
for(
|
|
; // Already set
|
|
*pchEntryOrig==' ' || *pchEntryOrig=='\t';
|
|
pchEntryOrig++
|
|
)
|
|
{}
|
|
|
|
// pchEntryOrig is now at the start of the class name. Copy till an invalid char is reached.
|
|
pchClass = PlaceFileClass;
|
|
while(*pchEntryOrig!=0 && *pchEntryOrig!=' ' && *pchEntryOrig!='\t' && *pchEntryOrig!='!') {
|
|
*pchClass++ = *pchEntryOrig++;
|
|
}
|
|
*pchClass = 0; // NULL terminate
|
|
|
|
if(pchClass == PlaceFileClass) { // No class name specified!
|
|
if (fVerbose) {
|
|
fprintf( stdout, "BINPLACE : warning BNP0000: No class name in entry \"%s\"\n", PlaceFileEntry ) ;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
if (PlaceFileNewName != NULL) {
|
|
*PlaceFileNewName = strchr(PlaceFileEntry,'!');
|
|
if(*PlaceFileNewName) {
|
|
*(*PlaceFileNewName)++ = 0; // Set the '!' to NULL, and skip past it to the Newname.
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|