Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

418 lines
10 KiB

//+==========================================================================
//
// File: CDir.cxx
//
// Purpose: Define the CDirectory class.
//
// This class is used to represent a directory name.
// Along with maintaining the name, it can determine
// the type of FileSystem.
//
//+==========================================================================
// --------
// Includes
// --------
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <wtypes.h>
#include "CFMEx.hxx"
#include "CDir.hxx"
//+------------------------------------------------------------------------------
//
// Function: CDirectory::Initialize (no arguments)
//
// Synopsis: Generate a directory name, using the TEMP environment
// variable, and use it to initialize this object.
//
// Inputs: None.
//
// Outputs: TRUE if the function succeeds, FALSE otherwise.
//
//+------------------------------------------------------------------------------
BOOL CDirectory::Initialize()
{
// ---------------
// Local Variables
// ---------------
// Assume failure for now.
BOOL bSuccess = FALSE;
// The TEMP environment variable.
WCHAR wszSystemTempPath[ MAX_PATH + sizeof( L'\0' )];
// Reset the error code.
m_lError = 0L;
// ----------
// Get %TEMP%
// ----------
if( !GetTempPath( MAX_PATH,
wszSystemTempPath )
)
{
m_lError = GetLastError();
EXIT( L"GetTempPath() failed (%d)" );
}
// ----------------------
// Initialize this object
// ----------------------
// Initialize using the temporary path. We must never pass a NULL here,
// or we'll cause an infinite recursion.
if( wszSystemTempPath == NULL )
EXIT( L"Invalid temporary path" );
bSuccess = Initialize( wszSystemTempPath );
// ----
// Exit
// ----
Exit:
return( bSuccess );
}
//+-----------------------------------------------------------------------
//
// Function: CDirectory::Initialize (with an ANSI string)
//
// Synopsis: This function converts the ANSI string to a Unicode
// string, then initializes the object with it.
//
// Inputs: A Unicode string.
//
// Outputs: TRUE if the function succeeds, FALSE otherwise.
//
//+-----------------------------------------------------------------------
BOOL CDirectory::Initialize( LPCSTR szDirectory )
{
// ---------------
// Local Variables
// ---------------
// Assume failure.
BOOL bSuccess = FALSE;
// A buffer for the Unicode path
WCHAR wszDirectory[ MAX_UNICODE_PATH + sizeof( L'\0' )];
// -----
// Begin
// -----
// Initialize the error code.
m_lError = 0L;
// If we were givin a NULL path, use the version of Initialize
// that requires no path.
if( szDirectory == NULL )
{
bSuccess = Initialize();
goto Exit;
}
// Convert the Ansi name to Unicode.
if( m_lError = (long) AnsiToUnicode( szDirectory,
wszDirectory,
strlen( szDirectory )
)
)
{
EXIT( L"Unable to convert directory to Unicode" );
}
// Initialize using the temporary path. We must never pass a NULL here,
// or we'll cause an infinite recursion.
if( wszDirectory == NULL )
EXIT( L"Invalid Directory (internal error)" );
bSuccess = Initialize( wszDirectory );
// ----
// Exit
// ----
Exit:
return( bSuccess );
}
//+-----------------------------------------------------------------------
//
// Function: CDirectory::Initialize (with a Unicode string)
//
// Synopsis: This function is the only form of Initialize
// (there are several variations of the Initialize member)
// which really initializes the object. It stores the
// directory name, and determines the type of filesystem
// on which it resides.
//
// Inputs: A Unicode string.
//
// Outputs: TRUE if the function succeeds, FALSE otherwise.
//
//+-----------------------------------------------------------------------
BOOL CDirectory::Initialize( LPCWSTR wszDirectory )
{
// ---------------
// Local Variables
// ---------------
// Assume failure.
BOOL bSuccess = FALSE;
// Buffers for the root of the path and for the volume name.
WCHAR wszDirectoryRoot[ MAX_PATH + sizeof( L'\0' )];
WCHAR wszVolumeName[ MAX_PATH + sizeof( L'\0' )];
// Parameters to GetVolumeInformation which we won't use.
DWORD dwMaxComponentLength = 0L;
DWORD dwFileSystemFlags = 0L;
// -----
// Begin
// -----
// Initialize the error code.
m_lError = 0L;
// If we were given a NULL path, use the variation of Initialization()
// which does not require one. Note that we will then be called again,
// but this time with a path.
if( wszDirectory == NULL )
{
bSuccess = Initialize();
goto Exit;
}
// Validate the path.
if( wcslen( wszDirectory ) > MAX_PATH )
{
m_lError = wcslen( wszDirectory );
EXIT( L"Input path is too long (%d)\n" );
}
// Save the path to our member buffer
wcscpy( m_wszDirectory, wszDirectory );
// ------------------------
// Get the file system name
// ------------------------
// Get the root path to the directory.
wcscpy( wszDirectoryRoot, wszDirectory );
MakeRoot( wszDirectoryRoot );
// Get the volume information, which will include the filesystem name.
if( !GetVolumeInformation( wszDirectoryRoot, // Root path name.
wszVolumeName, // Buffer for volume name
MAX_PATH, // Length of the above buffer
NULL, // Buffer for serial number
// Longest filename length.
&dwMaxComponentLength,
&dwFileSystemFlags, // Compression, etc.
m_wszFileSystemName,// Buffer for the FS name.
MAX_PATH ) // Length of above buffer
)
{
m_lError = GetLastError();
EXIT( L"GetVolumeInformation() failed" );
}
// Determine the file system type from the name.
if( !wcscmp( m_wszFileSystemName, L"FAT" ))
m_FileSystemType = fstFAT;
else if( !wcscmp( m_wszFileSystemName, L"NTFS" ))
m_FileSystemType = fstNTFS;
else if( !wcscmp( m_wszFileSystemName, L"OFS" ))
m_FileSystemType = fstOFS;
else
m_FileSystemType = fstUnknown;
bSuccess = TRUE;
// ----
// Exit
// ----
Exit:
DisplayErrors( bSuccess, L"CDirectory::Initialize( wszDirectory )" );
return( bSuccess );
}
//
// GetRootLength
//
// This routine was simply copied from private\windows\shell\shelldll\tracker.cxx,
// and should not be modified here.
//
unsigned
CDirectory::GetRootLength(const WCHAR *pwszPath)
{
ULONG cwcRoot = 0;
m_lError = 0L;
if (pwszPath == 0)
pwszPath = L"";
if (*pwszPath == L'\\')
{
// If the first character is a path separator (backslash), this
// must be a UNC drive designator which must be of the form:
// <path-separator><path-separator>(<alnum>+)
// <path-separator>(<alnum>+)<path-separator>
//
// This covers drives like these: \\worf\scratch\ and
// \\savik\win4dev\.
//
pwszPath++;
cwcRoot++;
BOOL fMachine = FALSE;
BOOL fShare = FALSE;
if (*pwszPath == L'\\')
{
cwcRoot++;
pwszPath++;
while (*pwszPath != '\0' && *pwszPath != L'\\')
{
cwcRoot++;
pwszPath++;
fMachine = TRUE;
}
if (*pwszPath == L'\\')
{
cwcRoot++;
pwszPath++;
while (*pwszPath != '\0' && *pwszPath != L'\\')
{
cwcRoot++;
pwszPath++;
fShare = TRUE;
}
// If there weren't any characters in the machine or
// share portions of the UNC name, then the drive
// designator is bogus.
//
if (!fMachine || !fShare)
{
cwcRoot = 0;
}
}
else
{
cwcRoot = 0;
}
}
else
{
cwcRoot = 0;
}
}
else
if (iswalpha(*pwszPath))
{
// If the first character is an alphanumeric, we must have
// a drive designator of this form:
// (<alnum>)+<drive-separator><path-separator>
//
// This covers drives like these: a:\, c:\, etc
//
pwszPath++;
cwcRoot++;
if (*pwszPath == L':')
{
cwcRoot++;
pwszPath++;
}
else
{
cwcRoot = 0;
}
}
// If we have counted one or more characters in the root and these
// are followed by a component separator, we need to add the separator
// to the root length. Otherwise this is not a valid root and we need
// to return a length of zero.
//
if ((cwcRoot > 0) && (*pwszPath == L'\\'))
{
cwcRoot++;
}
else
{
cwcRoot = 0;
}
return (cwcRoot);
}
//
// MakeRoot
//
// This routine was simply copied from private\windows\shell\shelldll\tracker.cxx,
// and should not be modified here.
//
VOID
CDirectory::MakeRoot(WCHAR *pwszPath)
{
unsigned rootlength = GetRootLength(pwszPath);
m_lError = 0L;
if (rootlength)
{
pwszPath[rootlength] = L'\0';
}
}