582 lines
23 KiB
C++
582 lines
23 KiB
C++
/*****************************************************************************************************************
|
|
|
|
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;
|
|
|
|
}
|