mirror of https://github.com/tongzx/nt5src
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.
772 lines
22 KiB
772 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
exclproc.cpp
|
|
|
|
Abstract:
|
|
|
|
Exclude processing mechanism. Processes the FilesNotToBackup key and
|
|
zero or more exclude files with exclude rules.
|
|
|
|
Author:
|
|
|
|
Stefan R. Steiner [ssteiner] 03-21-2000
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "stdafx.h"
|
|
#include "match.h"
|
|
|
|
#include <shlobj.h>
|
|
|
|
static VOID
|
|
FsdExpandEnvironmentStrings(
|
|
IN LPCWSTR pwszInput,
|
|
OUT CBsString &cwsExpandedStr
|
|
);
|
|
|
|
static BOOL
|
|
FsdEnsureLongNames(
|
|
IN OUT CBsString& exclude_spec
|
|
);
|
|
|
|
SFsdExcludeRule::~SFsdExcludeRule()
|
|
{
|
|
delete( psVolId );
|
|
psVolId = NULL;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints out information about one rule. If the rule caused files to be excluded
|
|
it prints out those file too.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
<Enter return values here>
|
|
|
|
--*/
|
|
VOID
|
|
SFsdExcludeRule::PrintRule(
|
|
IN FILE *fpOut,
|
|
IN BOOL bInvalidRulePrint
|
|
)
|
|
{
|
|
if ( bInvalidRulePrint )
|
|
{
|
|
if ( bInvalidRule )
|
|
fwprintf( fpOut, L"%-24s %-32s '%s'\n",
|
|
cwsExcludeFromSource.c_str(), cwsExcludeDescription.c_str(), cwsExcludeRule.c_str() );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Iterate though excluded file list
|
|
//
|
|
CBsString cwsExcludedFile;
|
|
CVssDLListIterator< CBsString > cExcludedFilesIter( cExcludedFileList );
|
|
if ( cExcludedFilesIter.GetNext( cwsExcludedFile ) )
|
|
{
|
|
//
|
|
// At least one file excluded, print the header for the rule
|
|
//
|
|
fwprintf( fpOut, L"%-24s %-32s '%s'\n",
|
|
cwsExcludeFromSource.c_str(), cwsExcludeDescription.c_str(), cwsExcludeRule.c_str() );
|
|
|
|
//
|
|
// Now iterate
|
|
//
|
|
do
|
|
{
|
|
fwprintf( fpOut, L"\t%s\n", cwsExcludedFile.c_str() );
|
|
} while( cExcludedFilesIter.GetNext( cwsExcludedFile ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
CFsdExclusionManager::CFsdExclusionManager(
|
|
IN CDumpParameters *pcDumpParameters
|
|
) : m_pcParams( pcDumpParameters )
|
|
{
|
|
if ( !m_pcParams->m_bDontUseRegistryExcludes )
|
|
{
|
|
ProcessRegistryExcludes( HKEY_LOCAL_MACHINE, L"HKEY_LOCAL_MACHINE" );
|
|
ProcessRegistryExcludes( HKEY_CURRENT_USER, L"HKEY_CURRENT_USER" );
|
|
}
|
|
|
|
CBsString cwsEXEFileStreamExcludeFile( m_pcParams->m_cwsArgv0 + L":ExcludeList" );
|
|
if ( ProcessOneExcludeFile( cwsEXEFileStreamExcludeFile ) == FALSE )
|
|
m_pcParams->DumpPrint( L" NOTE: Exclude file: '%s' not found",
|
|
cwsEXEFileStreamExcludeFile.c_str() );
|
|
|
|
ProcessExcludeFiles( m_pcParams->m_cwsFullPathToEXE );
|
|
|
|
CompileExclusionRules();
|
|
}
|
|
|
|
CFsdExclusionManager::~CFsdExclusionManager()
|
|
{
|
|
SFsdExcludeRule *pER;
|
|
|
|
//
|
|
// Iterate through the exclude rule list and delete each element
|
|
//
|
|
CVssDLListIterator< SFsdExcludeRule * > cExclRuleIter( m_cCompleteExcludeList );
|
|
while( cExclRuleIter.GetNext( pER ) )
|
|
delete pER;
|
|
}
|
|
|
|
VOID
|
|
CFsdExclusionManager::ProcessRegistryExcludes(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR pwszFromSource
|
|
)
|
|
{
|
|
LPWSTR buffer ;
|
|
HKEY key = NULL ;
|
|
DWORD stat ;
|
|
DWORD dwDisposition ;
|
|
DWORD dwDataSize;
|
|
DWORD dwIndex = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
m_pcParams->DumpPrint( L" Processing FilesNotToBackup reg key in %s", pwszFromSource );
|
|
|
|
buffer = new WCHAR[ FSD_MAX_PATH ];
|
|
if ( buffer == NULL )
|
|
throw E_OUTOFMEMORY;
|
|
|
|
try
|
|
{
|
|
stat = ::RegOpenKeyEx( hKey,
|
|
FSD_REG_EXCLUDE_PATH,
|
|
0,
|
|
KEY_READ,
|
|
&key ) ;
|
|
|
|
dwIndex = 0 ;
|
|
while ( stat == ERROR_SUCCESS )
|
|
{
|
|
WCHAR pwszValue[ MAX_PATH ];
|
|
DWORD dwValSize = MAX_PATH; // prefix #118830
|
|
DWORD dwType;
|
|
|
|
dwDataSize = FSD_MAX_PATH; // prefix #118830
|
|
|
|
stat = ::RegEnumValueW( key,
|
|
dwIndex,
|
|
pwszValue,
|
|
&dwValSize,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)buffer,
|
|
&dwDataSize ) ;
|
|
dwIndex++;
|
|
|
|
if ( ( stat == ERROR_SUCCESS ) && ( dwType == REG_MULTI_SZ ) )
|
|
{
|
|
LPWSTR p = buffer;
|
|
while ( *p )
|
|
{
|
|
SFsdExcludeRule *psExclRule;
|
|
|
|
//
|
|
// Now load up the exclude rule with the unprocessed
|
|
// information
|
|
//
|
|
psExclRule = new SFsdExcludeRule;
|
|
if ( psExclRule == NULL )
|
|
throw E_OUTOFMEMORY;
|
|
psExclRule->cwsExcludeFromSource = pwszFromSource;
|
|
psExclRule->cwsExcludeDescription = pwszValue;
|
|
psExclRule->cwsExcludeRule = p;
|
|
|
|
if ( m_pcParams->m_bPrintDebugInfo || m_pcParams->m_bNoHeaderFooter )
|
|
{
|
|
m_pcParams->DumpPrint( L" \"%s\" \"%s\"",
|
|
pwszValue, p );
|
|
}
|
|
|
|
m_cCompleteExcludeList.AddTail( psExclRule );
|
|
p += ::wcslen( p ) + 1;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
catch ( HRESULT hrCaught )
|
|
{
|
|
hr = hrCaught;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
if ( key != NULL )
|
|
{
|
|
::RegCloseKey( key ) ;
|
|
key = NULL ;
|
|
}
|
|
|
|
delete [] buffer ;
|
|
|
|
if ( FAILED( hr ) )
|
|
throw hr;
|
|
}
|
|
|
|
|
|
VOID
|
|
CFsdExclusionManager::ProcessExcludeFiles(
|
|
IN const CBsString& cwsPathToExcludeFiles
|
|
)
|
|
{
|
|
HANDLE hFind = INVALID_HANDLE_VALUE;
|
|
|
|
try
|
|
{
|
|
//
|
|
// Iterate through all files in the directory looking for
|
|
// files with .exclude extensions
|
|
//
|
|
DWORD dwRet;
|
|
WIN32_FIND_DATAW sFindData;
|
|
hFind = ::FindFirstFileExW(
|
|
cwsPathToExcludeFiles + L"*.exclude",
|
|
FindExInfoStandard,
|
|
&sFindData,
|
|
FindExSearchNameMatch,
|
|
NULL,
|
|
0 );
|
|
if ( hFind == INVALID_HANDLE_VALUE )
|
|
{
|
|
dwRet = ::GetLastError();
|
|
if ( dwRet == ERROR_NO_MORE_FILES || dwRet == ERROR_FILE_NOT_FOUND )
|
|
return;
|
|
else
|
|
{
|
|
m_pcParams->ErrPrint( L"CFsdExclusionManager::ProcessExcludeFiles - FindFirstFileEx( '%s' ) returned: dwRet: %d, skipping looking for .exclude files",
|
|
cwsPathToExcludeFiles.c_str(), ::GetLastError() );
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now run through the directory
|
|
//
|
|
do
|
|
{
|
|
// Check and make sure the file such as ".", ".." and dirs are not considered
|
|
if( ::wcscmp( sFindData.cFileName, L".") != 0 &&
|
|
::wcscmp( sFindData.cFileName, L"..") != 0 &&
|
|
!( sFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
|
|
{
|
|
ProcessOneExcludeFile( cwsPathToExcludeFiles + sFindData.cFileName );
|
|
}
|
|
} while ( ::FindNextFile( hFind, &sFindData ) );
|
|
}
|
|
catch ( ... )
|
|
{
|
|
m_pcParams->ErrPrint( L"CFsdExclusionManager::ProcessExcludeFiles: Caught an unknown exception, dirPath: '%s'", cwsPathToExcludeFiles.c_str() );
|
|
}
|
|
|
|
if ( hFind != INVALID_HANDLE_VALUE )
|
|
::FindClose( hFind );
|
|
}
|
|
|
|
|
|
BOOL
|
|
CFsdExclusionManager::ProcessOneExcludeFile(
|
|
IN const CBsString& cwsExcludeFileName
|
|
)
|
|
{
|
|
FILE *fpExclFile;
|
|
|
|
fpExclFile = ::_wfopen( cwsExcludeFileName, L"r" );
|
|
if ( fpExclFile == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
m_pcParams->DumpPrint( L" Processing exclude file: '%s'", cwsExcludeFileName.c_str() );
|
|
|
|
CBsString cwsInputLine;
|
|
while( ::fgetws( cwsInputLine.GetBuffer( FSD_MAX_PATH), FSD_MAX_PATH, fpExclFile ) )
|
|
{
|
|
cwsInputLine.ReleaseBuffer();
|
|
cwsInputLine = cwsInputLine.Left( cwsInputLine.GetLength() - 1 ); // get rid of '\n'
|
|
cwsInputLine.TrimLeft();
|
|
cwsInputLine.TrimRight();
|
|
|
|
//
|
|
// See if it is a comment, either // or #
|
|
//
|
|
if ( cwsInputLine[ 0 ] == L'#' || cwsInputLine.Left( 2 ) == L"//"
|
|
|| cwsInputLine.IsEmpty() )
|
|
continue;
|
|
|
|
if ( m_pcParams->m_bPrintDebugInfo || m_pcParams->m_bNoHeaderFooter )
|
|
{
|
|
m_pcParams->DumpPrint( L" %s", cwsInputLine.c_str() );
|
|
}
|
|
|
|
CBsString cwsLine( cwsInputLine );
|
|
SFsdExcludeRule *psExclRule;
|
|
psExclRule = new SFsdExcludeRule;
|
|
if ( psExclRule == NULL )
|
|
{
|
|
::fclose( fpExclFile );
|
|
throw E_OUTOFMEMORY;
|
|
}
|
|
|
|
INT iLeft;
|
|
INT iRight;
|
|
//
|
|
// This is gross. With the updated string class, this can
|
|
// be simplified.
|
|
//
|
|
iLeft = cwsLine.Find( L'\"' );
|
|
if ( iLeft != -1 )
|
|
{
|
|
cwsLine = cwsLine.Mid( iLeft + 1 );
|
|
iRight = cwsLine.Find( L'\"' );
|
|
if ( iRight != -1 )
|
|
{
|
|
psExclRule->cwsExcludeDescription = cwsLine.Left( iRight );
|
|
cwsLine = cwsLine.Mid( iRight + 1 );
|
|
iLeft = cwsLine.Find( L'\"' );
|
|
if ( iLeft != -1 )
|
|
{
|
|
cwsLine = cwsLine.Mid( iLeft + 1 );
|
|
iRight = cwsLine.Find( L'\"' );
|
|
if ( iRight != -1 )
|
|
{
|
|
psExclRule->cwsExcludeRule = cwsLine.Left( iRight );
|
|
psExclRule->cwsExcludeFromSource = cwsExcludeFileName.c_str() + cwsExcludeFileName.ReverseFind( L'\\' ) + 1;
|
|
m_cCompleteExcludeList.AddTail( psExclRule );
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pcParams->ErrPrint( L"Parse error in exclusion rule file '%s', rule text '%s', skipping",
|
|
cwsExcludeFileName.c_str(), cwsInputLine.c_str() );
|
|
}
|
|
|
|
delete psExclRule;
|
|
}
|
|
|
|
::fclose( fpExclFile );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
CFsdExclusionManager::CompileExclusionRules()
|
|
{
|
|
SFsdExcludeRule *psER;
|
|
|
|
//
|
|
// Iterate through the exclude rule list and compile each rule
|
|
//
|
|
CVssDLListIterator< SFsdExcludeRule * > cExclRuleIter( m_cCompleteExcludeList );
|
|
CBsString cws;
|
|
|
|
if ( m_pcParams->m_bPrintDebugInfo )
|
|
wprintf( L"Exclusion rule debug info:\n" );
|
|
|
|
while( cExclRuleIter.GetNext( psER ) )
|
|
{
|
|
INT i;
|
|
|
|
::FsdExpandEnvironmentStrings( psER->cwsExcludeRule, cws );
|
|
|
|
if ( m_pcParams->m_bPrintDebugInfo )
|
|
{
|
|
wprintf( L"\t%s : %s : %s : %s", psER->cwsExcludeFromSource.c_str(),
|
|
psER->cwsExcludeDescription.c_str(), psER->cwsExcludeRule.c_str(),
|
|
cws.c_str() );
|
|
}
|
|
|
|
//
|
|
// Get rid of leading spaces and lower case the whole mess
|
|
//
|
|
cws.TrimLeft();
|
|
cws.MakeUpper();
|
|
|
|
//
|
|
// First see if /s is at end of string
|
|
//
|
|
i = cws.Find( L"/S" );
|
|
if ( i > 0 )
|
|
{
|
|
cws = cws.Left( i );
|
|
psER->bInclSubDirs = TRUE;
|
|
}
|
|
cws.TrimRight();
|
|
|
|
//
|
|
// Now see if there are any wildcards
|
|
//
|
|
i = cws.FindOneOf( L"*?" );
|
|
if ( i != -1 )
|
|
{
|
|
psER->bWCInFileName = TRUE;
|
|
}
|
|
|
|
//
|
|
// Now see if this is for any volume
|
|
//
|
|
if ( cws.GetLength() >= 2 && cws[0] == L'\\' && cws[1] != L'\\' )
|
|
psER->bAnyVol = TRUE;
|
|
else if ( cws.GetLength() >= 2 && cws[1] != L':' )
|
|
psER->bAnyVol = TRUE;
|
|
|
|
if ( psER->bAnyVol )
|
|
{
|
|
if ( cws[0] == L'\\' )
|
|
{
|
|
// Get rid of first '\'
|
|
cws = cws.Mid( 1 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Specific volume case
|
|
//
|
|
CBsString cwsVolPath;
|
|
|
|
psER->psVolId = new SFsdVolumeId;
|
|
if ( psER->psVolId == NULL ) // Prefix 118832
|
|
{
|
|
m_pcParams->ErrPrint( L"CFsdExclusionManager::CompileExclusionRules - out of memory" );
|
|
throw E_OUTOFMEMORY; // Prefix #118832
|
|
}
|
|
|
|
if ( CFsdVolumeStateManager::GetVolumeIdAndPath( m_pcParams, cws, psER->psVolId, cwsVolPath ) != ERROR_SUCCESS )
|
|
psER->bInvalidRule = TRUE;
|
|
else
|
|
{
|
|
//
|
|
// Slice off the volume part of the path
|
|
//
|
|
cws = cws.Mid( cwsVolPath.GetLength() );
|
|
}
|
|
}
|
|
|
|
INT iFileNameOffset;
|
|
iFileNameOffset = cws.ReverseFind( L'\\' );
|
|
if ( iFileNameOffset == -1 )
|
|
{
|
|
//
|
|
// No dirpath
|
|
//
|
|
// psER->cwsDirPath = L"\\";
|
|
psER->cwsFileNamePattern = cws;
|
|
}
|
|
else
|
|
{
|
|
psER->cwsFileNamePattern = cws.Mid( iFileNameOffset + 1 );
|
|
psER->cwsDirPath = cws.Left( iFileNameOffset + 1 );
|
|
}
|
|
|
|
//
|
|
// Now convert the file name pattern into a form that the pattern matcher
|
|
// can use.
|
|
//
|
|
::FsdRtlConvertWildCards( psER->cwsFileNamePattern );
|
|
|
|
if ( m_pcParams->m_bPrintDebugInfo )
|
|
{
|
|
if ( psER->bInclSubDirs )
|
|
wprintf( L" - SubDir" );
|
|
|
|
if ( psER->bWCInFileName )
|
|
wprintf( L" - WC" );
|
|
|
|
if ( psER->bAnyVol )
|
|
wprintf( L" - AnyVol" );
|
|
|
|
wprintf( L" - VolId: 0x%08x, DirPath: '%s', FileName: '%s'",
|
|
( psER->psVolId ) ? psER->psVolId->m_dwVolSerialNumber : 0xFFFFFFFF,
|
|
psER->cwsDirPath.c_str(), psER->cwsFileNamePattern.c_str() );
|
|
|
|
if ( psER->bInvalidRule )
|
|
wprintf( L" - ERROR, invalid rule" );
|
|
wprintf( L"\n" );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
CFsdExclusionManager::GetFileSystemExcludeProcessor(
|
|
IN CBsString cwsVolumePath,
|
|
IN SFsdVolumeId *psVolId,
|
|
OUT CFsdFileSystemExcludeProcessor **ppcFSExcludeProcessor
|
|
)
|
|
{
|
|
CFsdFileSystemExcludeProcessor *pExclProc;
|
|
*ppcFSExcludeProcessor = NULL;
|
|
|
|
//
|
|
// Get a new exclude processor for the file system
|
|
//
|
|
pExclProc = new CFsdFileSystemExcludeProcessor( m_pcParams, cwsVolumePath, psVolId );
|
|
if ( pExclProc == NULL )
|
|
{
|
|
m_pcParams->ErrPrint( L"CFsdExclusionManager::CFsdGetFileSystemExcludeProcessor - Could not new a CFsdFileSystemExcludeProcessor object" );
|
|
throw E_OUTOFMEMORY;
|
|
}
|
|
|
|
SFsdExcludeRule *pER;
|
|
|
|
//
|
|
// Now go through the complete exclude list to find exclude rules that are relevant to
|
|
// this file system
|
|
//
|
|
CVssDLListIterator< SFsdExcludeRule * > cExclRuleIter( m_cCompleteExcludeList );
|
|
while( cExclRuleIter.GetNext( pER ) )
|
|
{
|
|
if ( !pER->bInvalidRule )
|
|
{
|
|
if ( pER->bAnyVol || pER->psVolId->IsEqual( psVolId ) )
|
|
{
|
|
pExclProc->m_cFSExcludeList.AddTail( pER );
|
|
}
|
|
}
|
|
}
|
|
|
|
*ppcFSExcludeProcessor = pExclProc;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Goes through the list of exclusion rules and dumps information about each.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
<Enter return values here>
|
|
|
|
--*/
|
|
VOID
|
|
CFsdExclusionManager::PrintExclusionInformation()
|
|
{
|
|
SFsdExcludeRule *pER;
|
|
|
|
CVssDLListIterator< SFsdExcludeRule * > cExclRuleIter( m_cCompleteExcludeList );
|
|
|
|
m_pcParams->DumpPrint( L"" );
|
|
m_pcParams->DumpPrint( L"----------------------------------------------------------------------------" );
|
|
m_pcParams->DumpPrint( L"Invalid exclusion rules (invalid because volume not found or parsing error)" );
|
|
m_pcParams->DumpPrint( L"----------------------------------------------------------------------------" );
|
|
m_pcParams->DumpPrint( L"From Application Exclusion rule" );
|
|
while( cExclRuleIter.GetNext( pER ) )
|
|
pER->PrintRule( m_pcParams->GetDumpFile(), TRUE );
|
|
|
|
m_pcParams->DumpPrint( L"" );
|
|
m_pcParams->DumpPrint( L"----------------------------------------------------------------------------" );
|
|
m_pcParams->DumpPrint( L"Files excluded by valid exclusion rule" );
|
|
m_pcParams->DumpPrint( L"----------------------------------------------------------------------------" );
|
|
m_pcParams->DumpPrint( L"From Application Exclusion rule" );
|
|
cExclRuleIter.Reset();
|
|
while( cExclRuleIter.GetNext( pER ) )
|
|
pER->PrintRule( m_pcParams->GetDumpFile(), FALSE );
|
|
}
|
|
|
|
|
|
CFsdFileSystemExcludeProcessor::CFsdFileSystemExcludeProcessor(
|
|
IN CDumpParameters *pcDumpParameters,
|
|
IN const CBsString& cwsVolumePath,
|
|
IN SFsdVolumeId *psVolId
|
|
) : m_pcParams( pcDumpParameters ),
|
|
m_cwsVolumePath( cwsVolumePath),
|
|
m_psVolId( NULL )
|
|
{
|
|
m_psVolId = new SFsdVolumeId;
|
|
if ( m_psVolId == NULL ) // Prefix #118829
|
|
throw E_OUTOFMEMORY;
|
|
*m_psVolId = *psVolId;
|
|
}
|
|
|
|
CFsdFileSystemExcludeProcessor::~CFsdFileSystemExcludeProcessor()
|
|
{
|
|
delete m_psVolId;
|
|
}
|
|
|
|
BOOL
|
|
CFsdFileSystemExcludeProcessor::IsExcludedFile(
|
|
IN const CBsString &cwsFullDirPath,
|
|
IN DWORD dwEndOfVolMountPointOffset,
|
|
IN const CBsString &cwsFileName
|
|
)
|
|
{
|
|
BOOL bFoundMatch = FALSE;
|
|
SFsdExcludeRule *pER;
|
|
CBsString cwsUpperFileName( cwsFileName );
|
|
CBsString cwsDirPath( cwsFullDirPath.Mid( dwEndOfVolMountPointOffset ) );
|
|
cwsUpperFileName.MakeUpper(); // Make uppercased for match check
|
|
cwsDirPath.MakeUpper();
|
|
|
|
// wprintf( L"Exclude proc: DirPath: %s, fileName: %s\n", cwsDirPath.c_str(), cwsUpperFileName.c_str() );
|
|
CVssDLListIterator< SFsdExcludeRule * > cExclRuleIter( m_cFSExcludeList );
|
|
while( !bFoundMatch && cExclRuleIter.GetNext( pER ) )
|
|
{
|
|
if ( pER->bInclSubDirs )
|
|
{
|
|
//
|
|
// First check most common case \XXX /s
|
|
//
|
|
if ( pER->cwsDirPath.GetLength() != 0 )
|
|
{
|
|
if ( ::wcsncmp( pER->cwsDirPath.c_str(), cwsDirPath.c_str(), pER->cwsDirPath.GetLength() ) != 0 )
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Fixed path check
|
|
//
|
|
if ( pER->cwsDirPath != cwsDirPath )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ( pER->bWCInFileName )
|
|
{
|
|
//
|
|
// Pattern match check
|
|
//
|
|
if ( ::FsdRtlIsNameInExpression( pER->cwsFileNamePattern, cwsUpperFileName ) )
|
|
bFoundMatch = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Constant string match
|
|
//
|
|
if ( pER->cwsFileNamePattern == cwsUpperFileName )
|
|
bFoundMatch = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( bFoundMatch )
|
|
{
|
|
pER->cExcludedFileList.AddTail( cwsFullDirPath + cwsFileName );
|
|
if ( m_pcParams->m_bPrintDebugInfo )
|
|
wprintf( L" EXCLUDING: %s%s\n", cwsFullDirPath.c_str(), cwsFileName.c_str() );
|
|
}
|
|
return bFoundMatch;
|
|
}
|
|
|
|
static VOID
|
|
FsdExpandEnvironmentStrings(
|
|
IN LPCWSTR pwszInput,
|
|
OUT CBsString &cwsExpandedStr
|
|
)
|
|
{
|
|
BOOL isOK = FALSE;
|
|
|
|
LPWSTR pwszBuffer;
|
|
DWORD dwSize = ::ExpandEnvironmentStringsW( pwszInput, NULL, 0 ) ;
|
|
|
|
if ( pwszBuffer = cwsExpandedStr.GetBufferSetLength( dwSize + 1 ) )
|
|
{
|
|
isOK = ( 0 != ::ExpandEnvironmentStringsW( pwszInput, pwszBuffer, dwSize ) ) ;
|
|
cwsExpandedStr.ReleaseBuffer( ) ;
|
|
}
|
|
|
|
if ( !isOK )
|
|
{
|
|
// have never seen ExpandEnvironmentStrings fail... even with undefined env var... but just in case
|
|
cwsExpandedStr = pwszInput ;
|
|
}
|
|
|
|
::FsdEnsureLongNames( cwsExpandedStr );
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Originally from NtBackup.
|
|
This takes a path with short name components and expands them to long
|
|
name components. The path obviously has to exist on the system to expand
|
|
short names.
|
|
Uses a little shell magic (yuck) to translate it into a long name.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
TRUE if expanded properly
|
|
|
|
--*/
|
|
static BOOL
|
|
FsdEnsureLongNames(
|
|
IN OUT CBsString& exclude_spec
|
|
)
|
|
{
|
|
IShellFolder * desktop ;
|
|
ITEMIDLIST * id_list ;
|
|
ULONG parsed_ct = 0 ;
|
|
BOOL isOK = FALSE ; // initialize it, prefix bug # 180281
|
|
CBsString path ;
|
|
int last_slash ;
|
|
|
|
// strip off the filename, and all that other detritus...
|
|
path = exclude_spec ;
|
|
if ( -1 != ( last_slash = path.ReverseFind( TEXT( '\\' ) ) ) )
|
|
{
|
|
path = path.Left( last_slash ) ;
|
|
|
|
if ( SUCCEEDED( SHGetDesktopFolder( &desktop ) ) )
|
|
{
|
|
WCHAR * ptr = path.GetBufferSetLength( FSD_MAX_PATH ) ;
|
|
|
|
if ( SUCCEEDED( desktop->ParseDisplayName( NULL, NULL, ptr, &parsed_ct, &id_list, NULL ) ) )
|
|
{
|
|
IMalloc * imalloc ;
|
|
|
|
isOK = SHGetPathFromIDList( id_list, ptr ) ;
|
|
|
|
SHGetMalloc( &imalloc ) ;
|
|
imalloc->Free( id_list ) ;
|
|
imalloc->Release( ) ;
|
|
}
|
|
|
|
path.ReleaseBuffer( ) ;
|
|
desktop->Release( ) ;
|
|
}
|
|
|
|
if ( isOK )
|
|
{
|
|
// put it back together with the new & improved path...
|
|
exclude_spec = path + exclude_spec.Mid( last_slash ) ;
|
|
}
|
|
}
|
|
|
|
return isOK;
|
|
}
|
|
|