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.
 
 
 
 
 
 

327 lines
11 KiB

/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2002 Microsoft Corporation
//
// Module Name:
// DirectoryUtils.cpp
//
// Description:
// Useful functions for manipulating directies.
//
// Maintained By:
// Galen Barbee (GalenB) 05-DEC-2000
//
// Revision History:
//
// Notes:
//
/////////////////////////////////////////////////////////////////////////////
#include "Pch.h"
#include "SmartClasses.h"
//////////////////////////////////////////////////////////////////////////////
// Type Definitions
//////////////////////////////////////////////////////////////////////////////
//
// Structure used to pass parameters between recursive calls to the
// gs_RecursiveEmptyDirectory() function.
//
struct SDirRemoveParams
{
WCHAR * m_pszDirName; // Pointer to the directory name buffer.
size_t m_cchDirNameLen; // Length of string currently in buffer (does not include '\0')
size_t m_cchDirNameMax; // Max length of string in buffer (does not include '\0')
signed int m_iMaxDepth; // Maximum recursion depth.
};
//////////////////////////////////////////////////////////////////////////////
// Forward Declarations.
//////////////////////////////////////////////////////////////////////////////
DWORD
DwRecursiveEmptyDirectory( SDirRemoveParams * pdrpParamsInOut );
//////////////////////////////////////////////////////////////////////////////
//++
//
// DWORD
// DwRecursiveEmptyDirectory
//
// Description:
// Recursively removes the target directory and everything underneath it.
// This is a recursive function.
//
// Arguments:
// pdrpParamsInout
// Pointer to the object that contains the parameters for this recursive call.
//
// Return Value:
// ERROR_SUCCESS
// The directory was deleted
//
// Other Win32 error codes
// If something went wrong
//
//--
//////////////////////////////////////////////////////////////////////////////
DWORD
DwRecursiveEmptyDirectory( SDirRemoveParams * pdrpParamsInout )
{
DWORD dwError = ERROR_SUCCESS;
do
{
typedef CSmartResource<
CHandleTrait<
HANDLE
, BOOL
, FindClose
, INVALID_HANDLE_VALUE
>
> SmartFindFileHandle;
WIN32_FIND_DATA wfdCurFile;
size_t cchCurDirNameLen = pdrpParamsInout->m_cchDirNameLen;
ZeroMemory( &wfdCurFile, sizeof( wfdCurFile ) );
if ( pdrpParamsInout->m_iMaxDepth < 0 )
{
dwError = TW32( ERROR_DIR_NOT_EMPTY );
break;
} // if: the recursion is too deep.
//
// Check if the target directory name is too long. The two extra characters
// being checked for are '\\' and '*'.
//
if ( cchCurDirNameLen > ( pdrpParamsInout->m_cchDirNameMax - 2 ) )
{
dwError = TW32( ERROR_BUFFER_OVERFLOW );
break;
} // if: the target directory name is too long.
// Append "\*" to the end of the directory name
pdrpParamsInout->m_pszDirName[ cchCurDirNameLen ] = L'\\';
pdrpParamsInout->m_pszDirName[ cchCurDirNameLen + 1 ] = L'*';
pdrpParamsInout->m_pszDirName[ cchCurDirNameLen + 2 ] = L'\0';
++cchCurDirNameLen;
SmartFindFileHandle sffhFindFileHandle( FindFirstFile( pdrpParamsInout->m_pszDirName, &wfdCurFile ) );
if ( sffhFindFileHandle.FIsInvalid() )
{
dwError = TW32( GetLastError() );
break;
}
do
{
size_t cchFileNameLen;
// If the current file is a directory, make a recursive call to delete it.
if ( ( wfdCurFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 )
{
if ( ( wcscmp( wfdCurFile.cFileName, L"." ) != 0 )
&& ( wcscmp( wfdCurFile.cFileName, L".." ) != 0 )
)
{
cchFileNameLen = wcslen( wfdCurFile.cFileName );
// Append the subdirectory name past the last '\\' character.
THR( StringCchCopyW(
pdrpParamsInout->m_pszDirName + cchCurDirNameLen
, pdrpParamsInout->m_cchDirNameMax - cchCurDirNameLen
, wfdCurFile.cFileName
) );
// Update the parameter object.
--pdrpParamsInout->m_iMaxDepth;
pdrpParamsInout->m_cchDirNameLen = cchCurDirNameLen + cchFileNameLen;
// Delete the subdirectory.
dwError = TW32( DwRecursiveEmptyDirectory( pdrpParamsInout ) );
if ( dwError != ERROR_SUCCESS )
{
break;
} // if: an error occurred trying to empty this directory.
// Restore the parameter object. There is no need to restore m_cchDirNameLen
// since it is never used again in the RHS in this function.
++pdrpParamsInout->m_iMaxDepth;
if ( RemoveDirectory( pdrpParamsInout->m_pszDirName ) == FALSE )
{
dwError = TW32( GetLastError() );
break;
} // if: the current directory could not be removed.
} // if: the current directory is not "." or ".."
} // if: current file is a directory.
else
{
//
// This file is not a directory. Delete it.
//
cchFileNameLen = wcslen( wfdCurFile.cFileName );
if ( cchFileNameLen > ( pdrpParamsInout->m_cchDirNameMax - cchCurDirNameLen ) )
{
dwError = TW32( ERROR_BUFFER_OVERFLOW );
break;
}
// Append the file name to the directory name.
THR( StringCchCopyW(
pdrpParamsInout->m_pszDirName + cchCurDirNameLen
, pdrpParamsInout->m_cchDirNameMax - cchCurDirNameLen
, wfdCurFile.cFileName
) );
if ( DeleteFile( pdrpParamsInout->m_pszDirName ) == FALSE )
{
dwError = TW32( GetLastError() );
break;
} // if: DeleteFile failed.
} // else: current file is not a directory.
if ( FindNextFile( sffhFindFileHandle.HHandle(), &wfdCurFile ) == FALSE )
{
dwError = GetLastError();
if ( dwError == ERROR_NO_MORE_FILES )
{
// We have deleted all the files in this directory.
dwError = ERROR_SUCCESS;
}
else
{
TW32( dwError );
}
// If FindNextFile has failed, we are done.
break;
} // if: FindNextFile fails.
}
while( true ); // loop infinitely.
if ( dwError != ERROR_SUCCESS )
{
break;
} // if: something went wrong.
//
// If we are here, then all the files in this directory have been deleted.
//
// Truncate the directory name at the last '\'
pdrpParamsInout->m_pszDirName[ cchCurDirNameLen - 1 ] = L'\0';
}
while( false ); // dummy do while loop to avoid gotos.
return dwError;
} //*** DwRecursiveEmptyDirectory
//////////////////////////////////////////////////////////////////////////////
//++
//
// DWORD
// DwRemoveDirectory
//
// Description:
// Remove the target directory and everything underneath it.
// Calls DwRecursiveEmptyDirectory to do the actual work.
//
// Arguments:
// pcszTargetDirIn
// The directory to be removed. Note, this name cannot have trailing
// backslash '\' characters.
//
// iMaxDepthIn
// The maximum depth of the subdirectories that will be removed.
// Default value is 32. If this depth is exceeded, an exception
// is thrown.
//
// Return Value:
// ERROR_SUCCESS
// The directory was deleted
//
// Other Win32 error codes
// If something went wrong
//
// Remarks:
// If the length of the name of any of the files under pcszTargetDirIn
// exceeds MAX_PATH - 1, an error is returned.
//
//--
//////////////////////////////////////////////////////////////////////////////
DWORD
DwRemoveDirectory( const WCHAR * pcszTargetDirIn, signed int iMaxDepthIn )
{
WCHAR szDirBuffer[ MAX_PATH ];
SDirRemoveParams drpParams;
DWORD dwError = ERROR_SUCCESS;
WIN32_FILE_ATTRIBUTE_DATA wfadDirAttributes;
if ( pcszTargetDirIn == NULL )
{
goto Cleanup;
} // if: the directory name is NULL
ZeroMemory( &wfadDirAttributes, sizeof( wfadDirAttributes ) );
//
// Check if the directory exists.
//
if ( GetFileAttributesEx( pcszTargetDirIn, GetFileExInfoStandard, &wfadDirAttributes ) == FALSE )
{
dwError = GetLastError();
if ( dwError == ERROR_FILE_NOT_FOUND )
{
dwError = ERROR_SUCCESS;
} // if: the directory does not exist, this is not an error
else
{
TW32( dwError );
}
goto Cleanup;
} // if: we could not get the file attributes
if ( ( wfadDirAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0 )
{
// We are not going to delete files
goto Cleanup;
} // if: the path does not point to a directory
// Copy the input string to our buffer.
THR( StringCchCopyW( szDirBuffer, RTL_NUMBER_OF( szDirBuffer ), pcszTargetDirIn ) );
// Initialize the object that holds the parameters for the recursive call.
drpParams.m_pszDirName = szDirBuffer;
drpParams.m_cchDirNameLen = static_cast< UINT >( wcslen( szDirBuffer ) );
drpParams.m_cchDirNameMax = RTL_NUMBER_OF( szDirBuffer ) - 1;
drpParams.m_iMaxDepth = iMaxDepthIn;
// Call the actual recursive function to empty the directory.
dwError = TW32( DwRecursiveEmptyDirectory( &drpParams ) );
// If the directory was emptied, delete it.
if ( ( dwError == ERROR_SUCCESS ) && ( RemoveDirectory( pcszTargetDirIn ) == FALSE ) )
{
dwError = TW32( GetLastError() );
goto Cleanup;
} // if: the current directory could not be removed.
Cleanup:
return dwError;
} //*** DwRemoveDirectory