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.
 
 
 
 
 
 

260 lines
8.1 KiB

//
// copied from fusion\util\io.cpp with minor changes
//
// xiaoyuw@ 09/05/2001
//
#include "stdinc.h"
#include "macros.h"
#include "fusionbuffer.h"
#include "fusionhandle.h"
#include "fuseio.h"
static BOOL
FusionpIsDotOrDotDot(
PCWSTR str
)
{
return ((str[0] == L'.') && ((str[1] == L'\0') || ((str[1] == L'.') && (str[2] == L'\0'))));
}
static BOOL
IsStarOrStarDotStar(
PCWSTR str
)
{
return (str[0] == '*'
&& (str[1] == 0 || (str[1] == '.' && str[2] == '*' && str[3] == 0)));
}
CDirWalk::ECallbackResult
CDirWalk::WalkHelper(
)
{
const PCWSTR* fileFilter = NULL;
BOOL fGotAll = FALSE;
BOOL fThisIsAll = FALSE;
CFindFile hFind;
SIZE_T directoryLength = m_strParent.Cch();
ECallbackResult result = eKeepWalking;
::ZeroMemory(&m_fileData, sizeof(m_fileData));
result |= m_callback(eBeginDirectory, this);
if (result & (eError | eSuccess))
{
goto Exit;
}
if ((result & eStopWalkingFiles) == 0)
{
for (fileFilter = m_fileFiltersBegin ; fileFilter != m_fileFiltersEnd ; ++fileFilter)
{
//
// FindFirstFile equates *.* with *, so we do too.
//
fThisIsAll = ::IsStarOrStarDotStar(*fileFilter);
fGotAll = fGotAll || fThisIsAll;
if (!m_strParent.Win32EnsureTrailingPathSeparator())
goto Error;
if (!m_strParent.Win32Append(*fileFilter, (*fileFilter != NULL) ? ::wcslen(*fileFilter) : 0))
goto Error;
hFind = ::FindFirstFileW(m_strParent, &m_fileData);
m_strParent.Left(directoryLength);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if (::FusionpIsDotOrDotDot(m_fileData.cFileName))
continue;
if (!m_strLastObjectFound.Win32Assign(m_fileData.cFileName, ::wcslen(m_fileData.cFileName)))
{
goto Error;
}
//
// we recurse on directories only if we are getting all of them
// otherwise we do them afterward
//
// the order directories are visited is therefore inconsistent, but
// most applications should be happy enough with the eEndDirectory
// notification (to implement rd /q/s)
//
if (m_fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (fThisIsAll && (result & eStopWalkingDirectories) == 0)
{
if (!m_strParent.Win32Append("\\", 1))
{
goto Error;
}
if (!m_strParent.Win32Append(m_fileData.cFileName, ::wcslen(m_fileData.cFileName)))
{
goto Error;
}
result |= WalkHelper();
}
}
else
{
if ((result & eStopWalkingFiles) == 0)
{
result |= m_callback(eFile, this);
}
}
m_strParent.Left(directoryLength);
if (result & (eError | eSuccess))
{
goto Exit;
}
if (fThisIsAll)
{
if ((result & eStopWalkingDirectories) &&
(result & eStopWalkingFiles))
{
if (!hFind.Win32Close())
{
goto Error;
}
goto StopWalking;
}
}
else
{
if (result & eStopWalkingFiles)
{
if (!hFind.Win32Close())
{
goto Error;
}
goto StopWalking;
}
}
} while(::FindNextFileW(hFind, &m_fileData));
if (::GetLastError() != ERROR_NO_MORE_FILES)
{
goto Error;
}
if (!hFind.Win32Close())
{
goto Error;
}
}
}
}
StopWalking:;
//
// make another pass with * to get all directories, if we haven't already
//
if (!fGotAll && (result & eStopWalkingDirectories) == 0)
{
if (!m_strParent.Win32Append("\\*", 2))
{
goto Error;
}
hFind = ::FindFirstFileW(m_strParent, &m_fileData);
m_strParent.Left(directoryLength);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if (::FusionpIsDotOrDotDot(m_fileData.cFileName))
continue;
if ((m_fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
{
continue;
}
if (!m_strLastObjectFound.Win32Assign(m_fileData.cFileName, ::wcslen(m_fileData.cFileName)))
{
goto Error;
}
if (!m_strParent.Win32Append("\\", 1))
{
goto Error;
}
if (!m_strParent.Win32Append(m_fileData.cFileName, ::wcslen(m_fileData.cFileName)))
{
goto Error;
}
result |= WalkHelper();
m_strParent.Left(directoryLength);
if (result & (eError | eSuccess))
{
goto Exit;
}
if (result & eStopWalkingDirectories)
{
goto StopWalkingDirs;
}
} while(::FindNextFileW(hFind, &m_fileData));
if (::GetLastError() != ERROR_NO_MORE_FILES)
{
goto Error;
}
StopWalkingDirs:
if (!hFind.Win32Close())
{
goto Error;
}
}
}
::ZeroMemory(&m_fileData, sizeof(m_fileData));
result |= m_callback(eEndDirectory, this);
if (result & (eError | eSuccess))
{
goto Exit;
}
result = eKeepWalking;
Exit:
if ((result & eStopWalkingDeep) == 0)
{
result &= ~(eStopWalkingFiles | eStopWalkingDirectories);
}
if (result & eError)
{
result |= (eStopWalkingFiles | eStopWalkingDirectories | eStopWalkingDeep);
}
return result;
Error:
result |= eError;
goto Exit;
}
CDirWalk::CDirWalk()
{
const static PCWSTR defaultFileFilter[] = { L"*" };
m_fileFiltersBegin = defaultFileFilter;
m_fileFiltersEnd = defaultFileFilter + NUMBER_OF(defaultFileFilter);
}
BOOL
CDirWalk::Walk()
{
BOOL fSuccess = FALSE;
//
// Save off the original path length before we go twiddling m_strParent
//
m_cchOriginalPath = m_strParent.Cch();
ECallbackResult result = WalkHelper();
if (result & eError)
{
if (::GetLastError() == ERROR_SUCCESS) // forget to set lasterror ?
::SetLastError(ERROR_INSTALL_FAILURE);
goto Exit;
}
fSuccess = TRUE;
Exit:
return fSuccess;
}