|
|
/*****************************************************************************************************************
FILENAME: Exclude.cpp
COPYRIGHT� 2001 Microsoft Corporation and Executive Software International, Inc.
DESCRIPTION: Handles exclusion of files.
*/
#include "stdafx.h"
#include<nt.h>
#include<ntrtl.h>
#include<nturtl.h>
#include <windows.h>
extern "C" { #include "SysStruc.h"
} #include "ErrMacro.h"
#include "DfrgCmn.h"
#include "DfrgEngn.h"
#include "DfrgNtfs.h" //Includes function prototype for CheckPagefileNameMatch which is the same in FAT.
#include "Alloc.h"
#include "GetReg.h"
#include "LoadFile.h"
#include "Exclude.h"
#include "Expand.h"
/*****************************************************************************************************************
COPYRIGHT� 2001 Microsoft Corporation and Executive Software International, Inc.
INPUT + OUTPUT: IN cExcludeFile - The name of the file to check for exclusion. OUT phExcludeList - Pointer to handle for memory to be alloced and filled with the list of excluded files.
GLOBALS: None.
RETURN: TRUE - Success. FALSE - Fatal Error. */
BOOL GetExcludeFile( IN PTCHAR cExcludeFile, OUT PHANDLE phExcludeList ) { HKEY hValue = NULL; TCHAR cRegValue[MAX_PATH]; DWORD dwRegValueSize = sizeof(cRegValue); DWORD dwExcludeFileSize = 0;
//0.0E00 Get the install path.
// todo NOTE: SFP will prevent us from using the system32 folder for this purpose!
EF(GetRegValue(&hValue, TEXT("SOFTWARE\\Microsoft\\Dfrg"), (PTCHAR)TEXT("PathName"), cRegValue, &dwRegValueSize) == ERROR_SUCCESS);
EF_ASSERT(RegCloseKey(hValue)==ERROR_SUCCESS);
//Translate any environment variables in the string.
EF_ASSERT(ExpandEnvVars(cRegValue));
//0.0E00 Print out the name of the exclude file.
lstrcat(cRegValue, TEXT("\\")); lstrcat(cRegValue, cExcludeFile);
//0.0E00 Read the file into memory.
*phExcludeList = LoadFile((PTCHAR)cRegValue, &dwExcludeFileSize, FILE_SHARE_READ|FILE_SHARE_WRITE, OPEN_EXISTING);
//0.0E00 Print out whether or not the file was loaded.
if(*phExcludeList != NULL) { Message(TEXT("Loaded exclude file"), S_OK, cRegValue); } else { Message(TEXT("No exclude file"), S_OK, cRegValue); } Message(TEXT(""), -1, NULL); return TRUE; } /*****************************************************************************************************************
COPYRIGHT� 2001 Microsoft Corporation and Executive Software International, Inc.
ROUTINE DESCRIPTION: Check to see if this file is excluded.
INPUT + OUTPUT: IN VolData.cFileName - The name of the file which is excluded. IN VolData.FileSystem - Which file system the drive is.
GLOBALS: None.
RETURN: TRUE - File is not excluded. FALSE - File is excluded. */
BOOL CheckFileForExclude( IN CONST BOOL fAcceptNameOnly ) { PTCHAR pFileName = VolData.vFileName.GetBuffer(); PTCHAR pExcludeList = NULL; PTCHAR pExcludeListEnd = NULL; UINT ExcludeLength; int i;
if (!pFileName) { return FALSE; }
if((VolData.FileSystem == FS_FAT || VolData.FileSystem == FS_FAT32) && (CompareString(LOCALE_INVARIANT,// locale identifier
NORM_IGNORECASE, // comparison-style options
TEXT("BOOTSECT.DOS"), // pointer to first string
-1, // null terminated first string
pFileName+3, // pointer to second string
-1) == 2)){ // null terminated second string
return FALSE; }
// Look get the file name from after the last slash.
TCHAR *cFileName = wcsrchr(VolData.vFileName.GetBuffer(), L'\\');
if (fAcceptNameOnly) { if (!cFileName) { cFileName = pFileName; } } else { //If there was no path to extract, then bail.
EF_ASSERT(cFileName); // start at first character after the last backslash
cFileName++; }
//Check to see if this is a pagefile.
if(CheckPagefileNameMatch(cFileName, pPageFileNames)){ return FALSE; } //sks bug#200579 removed ShellIconCache from the list
// Do not move the file safeboot.fs
// Moving this file can cause desktop problems.
// Raffi - 20-Oct-1997 - added in Build V2.0.172
if (lstrlen(pFileName) >= lstrlen(TEXT("safeboot.fs"))) { i = lstrlen(pFileName) - lstrlen(TEXT("safeboot.fs")); if(CompareString(LOCALE_INVARIANT,// locale identifier
NORM_IGNORECASE, // comparison-style options
TEXT("safeboot.fs"), // pointer to first string
-1, // null terminated first string
pFileName+i, // pointer to second string
-1) == 2){ // null terminated second string
Message(TEXT("Excluding safeboot.fs"), -1, pFileName); return FALSE; } } // Do not move the file safeboot.csv
// Moving this file can cause desktop problems.
// Raffi - 20-Oct-1997 - added in Build V2.0.172
if (lstrlen(pFileName) >= lstrlen(TEXT("safeboot.csv"))) { i = lstrlen(pFileName) - lstrlen(TEXT("safeboot.csv")); if(CompareString(LOCALE_INVARIANT,// locale identifier
NORM_IGNORECASE, // comparison-style options
TEXT("safeboot.csv"), // pointer to first string
-1, // null terminated first string
pFileName+i, // pointer to second string
-1) == 2){ // null terminated second string
Message(TEXT("Excluding safeboot.csv"), -1, pFileName); return FALSE; } } // Do not move the file safeboot.rsv
// Moving this file can cause desktop problems.
// Raffi - 20-Oct-1997 - added in Build V2.0.172
if (lstrlen(pFileName) >= lstrlen(TEXT("safeboot.rsv"))) { i = lstrlen(pFileName) - lstrlen(TEXT("safeboot.rsv")); if(CompareString(LOCALE_INVARIANT,// locale identifier
NORM_IGNORECASE, // comparison-style options
TEXT("safeboot.rsv"), // pointer to first string
-1, // null terminated first string
pFileName+i, // pointer to second string
-1) == 2){ // null terminated second string
Message(TEXT("Excluding safeboot.rsv"), -1, pFileName); return FALSE; } } // Do not move the file hiberfil.sys
// Moving this file can cause problems.
if (lstrlen(pFileName) >= lstrlen(TEXT("hiberfil.sys"))) { i = lstrlen(pFileName) - lstrlen(TEXT("hiberfil.sys")); if(CompareString(LOCALE_INVARIANT,// locale identifier
NORM_IGNORECASE, // comparison-style options
TEXT("hiberfil.sys"), // pointer to first string
-1, // null terminated first string
pFileName+i, // pointer to second string
-1) == 2){ // null terminated second string
Message(TEXT("Excluding hiberfil.sys"), -1, pFileName); return FALSE; } }
// Do not move the file memory.dmp
// Moving this file can cause problems.
if (lstrlen(pFileName) >= lstrlen(TEXT("memory.dmp"))) { i = lstrlen(pFileName) - lstrlen(TEXT("memory.dmp")); if(CompareString(LOCALE_INVARIANT,// locale identifier
NORM_IGNORECASE, // comparison-style options
TEXT("memory.dmp"), // pointer to first string
-1, // null terminated first string
pFileName+i, // pointer to second string
-1) == 2){ // null terminated second string
Message(TEXT("Excluding memory.dmp"), -1, pFileName); return FALSE; } }
//0.0E00 No Match
if(VolData.hExcludeList == NULL){ return TRUE; }
BOOL bReturnValue;
__try{ //0.0E00 Lock the memory and get pointer to the memory
pExcludeList = (PTCHAR) GlobalLock(VolData.hExcludeList); if (pExcludeList == (PTCHAR) NULL){ EH_ASSERT(FALSE); bReturnValue = FALSE; __leave; }
//0.0E00 Get the pointer to the end of the exclude list
pExcludeListEnd = pExcludeList + GlobalSize(VolData.hExcludeList);
//0.0E00 Loop until match or end of Exclude List
while (pExcludeList < pExcludeListEnd){
ExcludeLength = lstrlen(pExcludeList); //
// if(CompareString(LOCALE_INVARIANT, // locale identifier
// NORM_IGNORECASE, // comparison-style options
// pExcludeList, // pointer to first string
// ExcludeLength, // size, in bytes or characters, of first string
// pFileName, // pointer to second string
// ExcludeLength) == 2){ // size, in bytes or characters, of second string
//
// //0.0E00 If there is a match then this file should be excluded.
// if((lstrlen(pFileName) == (int)ExcludeLength) || (pFileName[ExcludeLength] == TEXT('\\'))){
// //0.0E00 Exclude the file.
// Message(TEXT("Excluding File."), -1, pFileName);
// return FALSE;
// }
// }
// Check to see if it is a wild string type of exclusion *RA*
// It is not case sensitive
if (lStrWildCmp(pFileName, pExcludeList, FALSE)) { //0.0E00 Exclude the file.
Message(TEXT("Excluding File."), -1, pFileName); bReturnValue = FALSE; __leave; } //0.0E00 Set pointer to next record
pExcludeList += ExcludeLength + 2; } //0.0E00 No Match
bReturnValue = TRUE; }
__finally { if (pExcludeList) { GlobalUnlock(VolData.hExcludeList); } }
return bReturnValue; } /*****************************************************************************************************************
COPYRIGHT� 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: This routine does a wild string comparison of a given Source string and a Pattern string that may contain wild string characters (*, ?). INPUT: pOrigSourceString - Pointer to null terminated Source String to check for pattern match on. pOrigPatternString - Pointer to null terminated string containing the match pattern. bCaseType - TRUE=Case Sensitive comparison, FALSE=Non-Case Sensitive comparison RETURN: Success - TRUE - It was a match. Failure - FALSE - It was NOT a match. */
BOOL lStrWildCmp ( IN PTCHAR pOrigSourceString, IN PTCHAR pOrigPatternString, IN BOOL bCaseType ) { TCHAR cSource[500]; // Local copy of Source String
TCHAR cPattern[500]; // Local copy of Match Pattern String
PTCHAR pSource; // Pointer into our local Source String
PTCHAR pPattern; // Pointer into our local Match Pattern String
PTCHAR pEndPattern; // Pointer to the end of our local Match Pattern String
DWORD dwCompareFlag=0; // Flag used in CompareString function
BOOL bMatchFound; int nchars; // Number of characters in pattern section that we are checking against.
int lastn; // Indicates if last char was or was not, a cWildn (0=No, 1=Yes)
// Define some characters we use
TCHAR cWildn = {'*'}; TCHAR cWild1 = {'?'}; TCHAR cEndstr = {'\0'}; PTCHAR cStopset = TEXT("*?\0"); // note order is cWildn/cWild1
// Verify that a valid Source and Pattern string was passed in. If not, return failure status.
if ((pOrigPatternString == NULL) || (lstrlen(pOrigPatternString) == 0)) { return FALSE; } if ((pOrigSourceString == NULL) || (lstrlen(pOrigSourceString) == 0)) { return FALSE; } // Check for the simple case of No wildcards in the pattern.
#ifndef UNICODE
if ((strchr(pOrigPatternString, cWildn) == NULL) && (strchr(pOrigPatternString, cWild1) == NULL)) { #else
if ((wcschr(pOrigPatternString, cWildn) == NULL) && (wcschr(pOrigPatternString, cWild1) == NULL)) { #endif
// This is a simple case of a 'straight' string comparison
// If the lengths do not equal, then the strings do not equal.
if (lstrlen(pOrigSourceString) != lstrlen(pOrigPatternString)) { // No Match
return FALSE; } else { // Set up CompareString flag for No Case-sensitive checking if selected
if (bCaseType == FALSE) { dwCompareFlag = NORM_IGNORECASE; } if(!lstrcmpi(pOrigSourceString, pOrigPatternString)){ // WRITE A REAL SHELL FOR COMPARESTRING!
// Compare strings
// if ((CompareString(LOCALE_INVARIANT,
// dwCompareFlag,
// pOrigSourceString,
// lstrlen(pOrigSourceString),
// pOrigPatternString,
// lstrlen(pOrigPatternString)
// )) == 2) {
// Match found
return TRUE; } else { // No Match found
return FALSE; } } } // There was wildcard(s) in the match pattern, so it is a more complex check
//
// Set up data for wildcard comparisons.
//
// Reset indicator that last char was not a cWildn(*) character
lastn = 0; // Make our own local copies of the strings
if (lstrcpy(cPattern, pOrigPatternString) == NULL) { return FALSE;} if (lstrcpy(cSource, pOrigSourceString) == NULL) { return FALSE;} // If Not case-sensitive check, then make both strings upper case
if (bCaseType == FALSE) { CharUpper(cPattern); CharUpper(cSource); //#ifndef UNICODE
// strupr(cPattern);
// strupr(cSource);
//#else
// wcsupr(cPattern);
// wcsupr(cSource);
//#endif
} // Set up pointers to strings
pSource = cSource; pPattern = cPattern; pEndPattern = pPattern + (lstrlen(cPattern) * sizeof(TCHAR)); // This section of the code will take the pattern string and extract each pattern section, where a
// string sections is seperated by one of the following:
//
// a) The start of the string
// b) The end of the string (0 termination)
// c) A wildcard character (* or ?)
//
// For each pattern section, it will then try to find a match in the source string. If a match is found, then
// the next pattern section is extracted and the next match check is made on the source string, starting at
// the source string location where the last match was found.
//
// There are several types of pattern sections to consider
// 1) *nnn* - Section with '*' on both ends. This means that the match be anywhere in the source string.
// 2) nnn* - '*' just at the section end, so the string must match starting at the current source string
// location.
// 3) *nnn - '*' just at the section start, so just the end of the source string is checked. For example,
// *.dat
// 4) ? - For single character wildcards, we just skip the next character in the source string to check.
//
//
while (pPattern <= pEndPattern) { switch (*pPattern) { // Case 1: Next pattern char is cWildn (*) character
// Indicate that last character was cWildn and continue on with check
case '*' : { pPattern = pPattern + 1; lastn = 1; break; } // End Case 1
// Case 2: Next pattern char is cWild1 (?) character
case '?' : { // Check where we are in the source string
if (*pSource != cEndstr) { // We are not at the end, so we know the next character is the Source String will be
// a match, so just increment to the next character and continue on with check.
pSource = pSource + 1; pPattern = pPattern + 1; lastn = 0; break; } else { // We are at the end of the Source string, so NO Match found
return FALSE; } } // End Case 2
// Case 3: End of the pattern string reached
case '\0' : { // If we are also at the end of the Source string, then all done with a Match found
if (*pSource == cEndstr) { return TRUE; } else { // If the last character was a '*', then all done with a Match found
if (lastn == 1) { return TRUE; } // If the last character was NOT a '*', then all done with NO Match found
else { return FALSE; } } } // End Case 3
// Case 4: Anything else (NON wild or terminating character), we get
// the next pattern section to check against the source string.
default : { // Get number of character in next pattern section
#ifndef UNICODE
nchars = strcspn(pPattern, cStopset); #else
nchars = wcscspn(pPattern, cStopset); #endif
// If the last character was Not a cWildn (*), then just
// check the pattern section starting at the current point in the source string.
if (lastn == 0) { // If a match found, then reset pattern and source pointers for the next sections to
// check against and start search for next section.
#ifndef UNICODE
if (strncmp(pPattern, pSource, nchars) == 0) { #else
if (wcsncmp(pPattern, pSource, nchars) == 0) { #endif
pPattern = pPattern + nchars; pSource = pSource + nchars; break; } else { // NO Match found, return back failure status
return FALSE; } } // The last character was a cWildn (*), but we need to see if
// the string ends the pattern and check that as a special case
// Check for special case of the last pattern section
if (nchars == (int)lstrlen(pPattern)) { // For the last pattern section case, if the length of the pattern section is greater
// than the source string section to check against, then there cannot be a match.
if ((int)lstrlen(pSource) < nchars) { return FALSE; } // For the last pattern section case, we just need to compare to the end section of the
// source string, adjust the source string pointer to this location (= 'cEndstr'-nchars),
// and go continue checking.
pSource = pSource + (lstrlen(pSource) - nchars); lastn = 0; break; } // It was not the special case, so since the last char was a cWildn (*), the match could be anywhere.
// So, we start checking at the current Source string location for a match with the pattern section.
// Note: If No Match is found, then it falls out of this loop.
bMatchFound = FALSE; while (*pSource != cEndstr) { // If a match found, then reset pattern and source pointers for the next sections to
// check against and start search for next section.
#ifndef UNICODE
if (strncmp(pPattern, pSource, nchars) == 0) { #else
if (wcsncmp(pPattern, pSource, nchars) == 0) { #endif
pPattern = pPattern + nchars; pSource = pSource + nchars; lastn = 0; bMatchFound = TRUE; break; } else { pSource = pSource + 1; } } // If no match found, then return back failure status
if (!bMatchFound) { return FALSE; } // else a match was found, so go check next pattern section
break; } // End Case 4
} // End Switch
} // End While
// It should never fall out of the while loop, because the checks within the loop should catch
// when processing is completed, but just in case, it will fail if it comes out of the loop.
return FALSE; }
|