Leaked source code of windows server 2003
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

#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;
}