1040 lines
25 KiB
C
1040 lines
25 KiB
C
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Copyright (c) 1997-1999 Microsoft Corporation
|
|||
|
// All rights reserved.
|
|||
|
//
|
|||
|
// File Name:
|
|||
|
// pathsup.c
|
|||
|
//
|
|||
|
// Description:
|
|||
|
// Some path support routines.
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
#include "pch.h"
|
|||
|
|
|||
|
static TCHAR g_szSetupMgrFileExtensions[MAX_PATH + 1] = _T("");
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CleanTrailingSlashes
|
|||
|
//
|
|||
|
// Purpose: Cleans up trailing slashes off pathnames. This is a support
|
|||
|
// routine for ConcatenatePaths().
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPTSTR lpBuffer - MAX_PATH buffer
|
|||
|
//
|
|||
|
// Returns: VOID
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
static VOID CleanTrailingSlashes(LPTSTR lpBuffer)
|
|||
|
{
|
|||
|
TCHAR *p = lpBuffer + lstrlen(lpBuffer) - 1;
|
|||
|
|
|||
|
while ( p >= lpBuffer && *p == _T('\\') )
|
|||
|
*p-- = _T('\0');
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CleanLeadingSlashes
|
|||
|
//
|
|||
|
// Purpose: Removes leading slashes from the given string.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPTSTR lpStr - str to clean
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// A pointer to the character after the run of back-slashes.
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
static LPTSTR CleanLeadingSlashes(LPTSTR lpStr)
|
|||
|
{
|
|||
|
TCHAR *p=lpStr;
|
|||
|
|
|||
|
while ( *p && *p == TEXT('\\') )
|
|||
|
p++;
|
|||
|
|
|||
|
return p;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: ConcatenatePaths
|
|||
|
//
|
|||
|
// Purpose: This function cats path components together. It makes sure
|
|||
|
// that there are not multiple slashes separating each item, and
|
|||
|
// that there isn't a trailing back-slash.
|
|||
|
//
|
|||
|
// The last string passed must be NULL.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPTSTR lpBuffer - MAX_PATH buffer
|
|||
|
// ...
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// TRUE if all is ok
|
|||
|
// FALSE if resultant string is >= MAX_PATH chars
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL __cdecl ConcatenatePaths(LPTSTR lpBuffer, ...)
|
|||
|
{
|
|||
|
LPTSTR lpString;
|
|||
|
va_list arglist;
|
|||
|
HRESULT hrCat;
|
|||
|
|
|||
|
va_start(arglist, lpBuffer);
|
|||
|
lpString = va_arg(arglist, LPTSTR);
|
|||
|
|
|||
|
while ( lpString != NULL ) {
|
|||
|
|
|||
|
if ( lstrlen(lpBuffer) + lstrlen(lpString) >= MAX_PATH )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
lpString = CleanLeadingSlashes(lpString);
|
|||
|
CleanTrailingSlashes(lpString);
|
|||
|
CleanTrailingSlashes(lpBuffer);
|
|||
|
|
|||
|
if ( lpBuffer[0] ) {
|
|||
|
hrCat=StringCchCat(lpBuffer, MAX_PATH, _T("\\"));
|
|||
|
hrCat=StringCchCat(lpBuffer, MAX_PATH, lpString);
|
|||
|
} else {
|
|||
|
lstrcpyn(lpBuffer, lpString, MAX_PATH);
|
|||
|
}
|
|||
|
|
|||
|
lpString = va_arg(arglist, LPTSTR);
|
|||
|
}
|
|||
|
|
|||
|
va_end(arglist);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: ParseDriveLetterOrUnc
|
|||
|
//
|
|||
|
// Purpose: Will parse past the \\srv\share\ or D:\ and return a pointer
|
|||
|
// to the character after that mess.
|
|||
|
//
|
|||
|
// Returns: Pointer to the pathname 1 char past the volume descriptor,
|
|||
|
// NULL if errors. GetLastError() will be valid when NULL
|
|||
|
// is returned.
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
// - Only pass in fully qualified pathnames. Use MyGetFullPath().
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
LPTSTR ParseDriveLetterOrUnc(LPTSTR lpFileName)
|
|||
|
{
|
|||
|
TCHAR *p=NULL;
|
|||
|
|
|||
|
//
|
|||
|
// If path is of form \\srv\share\, get a pointer past the whole mess.
|
|||
|
//
|
|||
|
// Note we start at lpFileName+3 because "srv" (in this example) must
|
|||
|
// be at least 1 character.
|
|||
|
//
|
|||
|
|
|||
|
if ( lpFileName[0] == _T('\\') && lpFileName[1] == _T('\\') ) {
|
|||
|
|
|||
|
//
|
|||
|
// Move past the computer name
|
|||
|
//
|
|||
|
|
|||
|
p = lpFileName + 2;
|
|||
|
|
|||
|
while( *p != _T('\\') )
|
|||
|
{
|
|||
|
if( *p == _T('\0') )
|
|||
|
{
|
|||
|
SetLastError( ERROR_BAD_PATHNAME );
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
|
|||
|
p++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
p++;
|
|||
|
|
|||
|
//
|
|||
|
// Scan past the share name
|
|||
|
//
|
|||
|
|
|||
|
while( *p != _T('\\') )
|
|||
|
{
|
|||
|
if( *p == _T('\0') )
|
|||
|
{
|
|||
|
SetLastError( ERROR_BAD_PATHNAME );
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
|
|||
|
p++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
p++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get past the D:\ if path is of that form
|
|||
|
//
|
|||
|
|
|||
|
if ( towupper(lpFileName[0]) >= _T('A') &&
|
|||
|
towupper(lpFileName[0]) <= _T('Z') &&
|
|||
|
lpFileName[1] == _T(':') &&
|
|||
|
lpFileName[2] == _T('\\') ) {
|
|||
|
|
|||
|
p = lpFileName + 3;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If we never set *p, then the path is not in a valid form.
|
|||
|
//
|
|||
|
|
|||
|
if ( p == NULL ) {
|
|||
|
SetLastError(ERROR_BAD_PATHNAME);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
return p;
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: GetComputerNameFromUnc
|
|||
|
//
|
|||
|
// Purpose: To strip out the computer name from a full UNC path.
|
|||
|
//
|
|||
|
// Example: \\computername\sharename\dir1\dir2 would return
|
|||
|
// \\computername
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// szComputerName is assumed to be MAX_PATH length
|
|||
|
//
|
|||
|
// Returns: VOID
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
// - Only pass in fully qualified pathnames. Use MyGetFullPath().
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
VOID
|
|||
|
GetComputerNameFromUnc( IN TCHAR *szFullUncPath,
|
|||
|
OUT TCHAR *szComputerName,
|
|||
|
IN DWORD cbSize) {
|
|||
|
|
|||
|
TCHAR *pString;
|
|||
|
|
|||
|
AssertMsg( szFullUncPath[0] == _T('\\') && szFullUncPath[1] == _T('\\'),
|
|||
|
"szFullUncPath is not a well formed net path" );
|
|||
|
|
|||
|
lstrcpyn( szComputerName, szFullUncPath, cbSize );
|
|||
|
|
|||
|
pString = &(szComputerName[2]);
|
|||
|
|
|||
|
//
|
|||
|
// Scan past the computer name
|
|||
|
//
|
|||
|
|
|||
|
while( *pString != _T('\\') )
|
|||
|
{
|
|||
|
if( *pString == _T('\0') )
|
|||
|
{
|
|||
|
AssertMsg( FALSE,
|
|||
|
"Bad UNC path");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
pString++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*pString = _T('\0');
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: GetComputerAndShareNameFromUnc
|
|||
|
//
|
|||
|
// Purpose: To strip out the computer and share name from a full UNC path.
|
|||
|
//
|
|||
|
// Example: \\computername\sharename\dir1\dir2 would return
|
|||
|
// \\computername\sharename
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// szComputerAndShareName is assumed to be MAX_PATH length
|
|||
|
//
|
|||
|
// Returns: VOID
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
// - Only pass in fully qualified pathnames. Use MyGetFullPath().
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
VOID
|
|||
|
GetComputerAndShareNameFromUnc( IN TCHAR *szFullUncPath,
|
|||
|
OUT TCHAR *szComputerAndShareName,
|
|||
|
IN DWORD cbSize) {
|
|||
|
|
|||
|
TCHAR *pString;
|
|||
|
|
|||
|
AssertMsg( szFullUncPath[0] == _T('\\') && szFullUncPath[1] == _T('\\'),
|
|||
|
"szFullUncPath is not a well formed net path");
|
|||
|
|
|||
|
lstrcpyn( szComputerAndShareName, szFullUncPath, cbSize );
|
|||
|
|
|||
|
pString = &(szComputerAndShareName[2]);
|
|||
|
|
|||
|
//
|
|||
|
// Scan past the computer name
|
|||
|
//
|
|||
|
|
|||
|
while( *pString != _T('\\') )
|
|||
|
{
|
|||
|
if( *pString == _T('\0') )
|
|||
|
{
|
|||
|
AssertMsg( FALSE,
|
|||
|
"Bad UNC path");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
pString++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pString++;
|
|||
|
|
|||
|
//
|
|||
|
// Scan past the share name
|
|||
|
//
|
|||
|
|
|||
|
while( *pString != _T('\\') )
|
|||
|
{
|
|||
|
if( *pString == _T('\0') )
|
|||
|
{
|
|||
|
//
|
|||
|
// already just the computer and share name so just return
|
|||
|
//
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
pString++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*pString = _T('\0');
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: MyGetFullPath
|
|||
|
//
|
|||
|
// Purpose: Small wrapper on GetFullPathName(). It assumes the buffer
|
|||
|
// is MAX_PATH.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// Pointer to filename part in the buffer, NULL if errors. The
|
|||
|
// Win32 error code will be valid if fails.
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
// - This function should be called whenever obtaining a pathname
|
|||
|
// from the user. Some of the other routines in this file
|
|||
|
// require a fully qualified and cleaned up pathname (i.e. no
|
|||
|
// trailing space and such).
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
LPTSTR MyGetFullPath(LPTSTR lpFileName)
|
|||
|
{
|
|||
|
TCHAR Buffer[MAX_PATH], *lpFilePart;
|
|||
|
|
|||
|
lstrcpyn(Buffer, lpFileName, AS(Buffer));
|
|||
|
|
|||
|
if ( ! GetFullPathName(Buffer,
|
|||
|
MAX_PATH,
|
|||
|
lpFileName,
|
|||
|
&lpFilePart) ) {
|
|||
|
lpFilePart = NULL;
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
return lpFilePart;
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: GetPathFromPathAndFilename
|
|||
|
//
|
|||
|
// Purpose: To obtain the just the path from a string that contains a path
|
|||
|
// and a filename.
|
|||
|
//
|
|||
|
// Arguments: LPTSTR lpPathAndFileName - the full path and filename
|
|||
|
// TCHAR *szPath - buffer the path is to be returned in, it is
|
|||
|
// assumed to be of MAX_PATH length
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// Inside szBuffer is just the path from the input of the path and file
|
|||
|
// name
|
|||
|
// BOOL - TRUE on success, FALSE on failure
|
|||
|
//
|
|||
|
//
|
|||
|
// Examples:
|
|||
|
// lpPathAndFileName szBuffer
|
|||
|
//
|
|||
|
// c:\foo\bar.exe returns c:\foo
|
|||
|
// c:\bar.exe c:\
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
BOOL
|
|||
|
GetPathFromPathAndFilename( IN LPTSTR lpPathAndFileName, OUT TCHAR *szPath, IN DWORD cbSize )
|
|||
|
{
|
|||
|
|
|||
|
INT iFileNameLength;
|
|||
|
INT iPathLength;
|
|||
|
INT iPathAndFileNameLength;
|
|||
|
TCHAR Buffer[MAX_PATH];
|
|||
|
TCHAR *lpFilePart;
|
|||
|
|
|||
|
lstrcpyn(Buffer, lpPathAndFileName, AS(Buffer));
|
|||
|
|
|||
|
if ( ! GetFullPathName(Buffer,
|
|||
|
MAX_PATH,
|
|||
|
lpPathAndFileName,
|
|||
|
&lpFilePart) ) {
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
iFileNameLength = lstrlen( lpFilePart );
|
|||
|
|
|||
|
iPathAndFileNameLength = lstrlen( lpPathAndFileName );
|
|||
|
|
|||
|
lstrcpyn( szPath, lpPathAndFileName, cbSize );
|
|||
|
|
|||
|
szPath[iPathAndFileNameLength - iFileNameLength] = _T('\0');
|
|||
|
|
|||
|
//
|
|||
|
// At this point szPath looks like either c:\foo\ or c:\
|
|||
|
// So trim the last back slash unless at the root
|
|||
|
//
|
|||
|
|
|||
|
iPathLength = lstrlen( szPath );
|
|||
|
|
|||
|
if( iPathLength > 3 )
|
|||
|
{
|
|||
|
szPath[iPathLength-1] = _T('\0');
|
|||
|
}
|
|||
|
|
|||
|
return( TRUE );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: MyGetDiskFreeSpace
|
|||
|
//
|
|||
|
// Purpose: Gets the free space in bytes on the given drive and returns
|
|||
|
// a LONGLONG (int64).
|
|||
|
//
|
|||
|
// The Win32 apis won't return an int64. Also, the Win32 apis
|
|||
|
// require d:\. But this function will accept any fully
|
|||
|
// qualified path.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPTSTR - any fully qualified path
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// LONGLONG - free space
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
LONGLONG
|
|||
|
MyGetDiskFreeSpace(LPTSTR Drive)
|
|||
|
{
|
|||
|
BOOL bRet;
|
|||
|
DWORD nSectorsPerCluster,
|
|||
|
nBytesPerSector,
|
|||
|
nFreeClusters,
|
|||
|
nTotalClusters;
|
|||
|
TCHAR DriveBuffer[MAX_PATH];
|
|||
|
|
|||
|
LONGLONG FreeBytes;
|
|||
|
HRESULT hrCat;
|
|||
|
|
|||
|
if( _istalpha( Drive[0] ) )
|
|||
|
{
|
|||
|
lstrcpyn(DriveBuffer, Drive, 4);
|
|||
|
DriveBuffer[3] = _T('\0');
|
|||
|
}
|
|||
|
else if( Drive[0] == _T('\\') )
|
|||
|
{
|
|||
|
GetComputerNameFromUnc( Drive, DriveBuffer, AS(DriveBuffer) );
|
|||
|
|
|||
|
hrCat=StringCchCat( DriveBuffer, AS(DriveBuffer), _T("\\") );
|
|||
|
|
|||
|
hrCat=StringCchCat( DriveBuffer, AS(DriveBuffer), WizGlobals.DistShareName );
|
|||
|
|
|||
|
hrCat=StringCchCat( DriveBuffer, AS(DriveBuffer), _T("\\") );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
AssertMsg(FALSE,
|
|||
|
"MyGetDiskFreeSpace failed, programming error, bad Drive parameter");
|
|||
|
}
|
|||
|
|
|||
|
bRet = GetDiskFreeSpace( DriveBuffer,
|
|||
|
&nSectorsPerCluster,
|
|||
|
&nBytesPerSector,
|
|||
|
&nFreeClusters,
|
|||
|
&nTotalClusters );
|
|||
|
|
|||
|
if( bRet == FALSE )
|
|||
|
{
|
|||
|
ReportErrorId( NULL,
|
|||
|
MSGTYPE_ERR | MSGTYPE_WIN32,
|
|||
|
IDS_ERR_UNABLE_TO_DETERMINE_FREE_SPACE,
|
|||
|
DriveBuffer );
|
|||
|
|
|||
|
return( 0 );
|
|||
|
}
|
|||
|
|
|||
|
FreeBytes = (LONGLONG) nFreeClusters *
|
|||
|
(LONGLONG) nBytesPerSector *
|
|||
|
(LONGLONG) nSectorsPerCluster;
|
|||
|
|
|||
|
return( FreeBytes );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: MySetupQuerySpaceRequiredOnDrive
|
|||
|
//
|
|||
|
// Purpose: Uses setupapi disk-space-list and returns the LONGLONG
|
|||
|
// of how many bytes are needed.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPTSTR - any fully qualified path
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// LONGLONG - free space
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
LONGLONG
|
|||
|
MySetupQuerySpaceRequiredOnDrive(HDSKSPC hDiskSpace, LPTSTR Drive)
|
|||
|
{
|
|||
|
BOOL bRet;
|
|||
|
LONGLONG llRequiredSpace;
|
|||
|
TCHAR DriveBuffer[MAX_PATH];
|
|||
|
|
|||
|
if( _istalpha( Drive[0] ) )
|
|||
|
{
|
|||
|
lstrcpyn(DriveBuffer, Drive, 3);
|
|||
|
DriveBuffer[2] = _T('\0');
|
|||
|
}
|
|||
|
else if( Drive[0] == _T('\\') )
|
|||
|
{
|
|||
|
|
|||
|
GetComputerAndShareNameFromUnc( Drive, DriveBuffer, AS(DriveBuffer) );
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
AssertMsg(FALSE,
|
|||
|
"SetupQuerySpaceRequiredOnDrive failed, programming error, bad Drive parameter");
|
|||
|
}
|
|||
|
|
|||
|
bRet = SetupQuerySpaceRequiredOnDrive(
|
|||
|
hDiskSpace,
|
|||
|
DriveBuffer,
|
|||
|
&llRequiredSpace,
|
|||
|
NULL, 0);
|
|||
|
|
|||
|
AssertMsg(bRet,
|
|||
|
"SetupQuerySpaceRequiredOnDrive failed, programming error");
|
|||
|
|
|||
|
return llRequiredSpace;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: IsPathOnLocalDiskDrive
|
|||
|
//
|
|||
|
// Purpose: Determines if the path is on a local disk drive or not.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPTSTR lpPath - fully qualified path
|
|||
|
//
|
|||
|
// Returns: BOOL
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL
|
|||
|
IsPathOnLocalDiskDrive(LPCTSTR lpPath)
|
|||
|
{
|
|||
|
UINT nDriveType;
|
|||
|
TCHAR szDrivePath[MAX_PATH + 1];
|
|||
|
|
|||
|
//
|
|||
|
// Use GetDriveType to determine if the path is a local or a network path
|
|||
|
//
|
|||
|
|
|||
|
lstrcpyn( szDrivePath, lpPath, AS(szDrivePath) );
|
|||
|
|
|||
|
if( szDrivePath[0] != _T('\\') )
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Truncate the path to the root dir
|
|||
|
//
|
|||
|
szDrivePath[3] = _T('\0');
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
nDriveType = GetDriveType( szDrivePath );
|
|||
|
|
|||
|
if( nDriveType == DRIVE_REMOTE )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return( TRUE );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: EnsureDirExists
|
|||
|
//
|
|||
|
// Purpose: Function that will iteratively create the given directory
|
|||
|
// by creating each piece of the pathname if necessary.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPTSTR lpDirName - dir name
|
|||
|
//
|
|||
|
// Returns: BOOL
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
// - This function requires a fully qualified pathname. Translate
|
|||
|
// pathnames using MyGetFullPath() first.
|
|||
|
//
|
|||
|
// - The Win32 error code will be valid upon failure.
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL EnsureDirExists(LPTSTR lpDirName)
|
|||
|
{
|
|||
|
BOOL bRestoreSlash;
|
|||
|
DWORD dwAttribs;
|
|||
|
TCHAR *p;
|
|||
|
|
|||
|
//
|
|||
|
// Parse off the D:\ or \\srv\shr\. The lasterror will already
|
|||
|
// be set by ParseDriveLetterOrUnc() if any errors occured.
|
|||
|
//
|
|||
|
|
|||
|
if ( (p = ParseDriveLetterOrUnc(lpDirName)) == NULL )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Now parse off each piece of the pathname and make sure dir exists
|
|||
|
//
|
|||
|
|
|||
|
while ( *p ) {
|
|||
|
|
|||
|
// find next \ or end // of pathname
|
|||
|
|
|||
|
while ( *p && *p != _T('\\') )
|
|||
|
p++;
|
|||
|
|
|||
|
bRestoreSlash = FALSE;
|
|||
|
|
|||
|
if ( *p == _T('\\') ) {
|
|||
|
*p = _T('\0');
|
|||
|
bRestoreSlash = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
// see if a file with that name already exists
|
|||
|
|
|||
|
dwAttribs = GetFileAttributes(lpDirName);
|
|||
|
if ( dwAttribs != (DWORD) -1 &&
|
|||
|
!(dwAttribs & FILE_ATTRIBUTE_DIRECTORY) ) {
|
|||
|
|
|||
|
if ( bRestoreSlash )
|
|||
|
*p = _T('\\');
|
|||
|
|
|||
|
SetLastError(ERROR_ALREADY_EXISTS);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// create the dir and allow a failure if the dir already exists
|
|||
|
|
|||
|
if ( !CreateDirectory(lpDirName, NULL) &&
|
|||
|
GetLastError() != ERROR_ALREADY_EXISTS ) {
|
|||
|
|
|||
|
if ( bRestoreSlash )
|
|||
|
*p = _T('\\');
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if ( bRestoreSlash )
|
|||
|
*p = _T('\\');
|
|||
|
|
|||
|
// advance to next piece of the pathname
|
|||
|
|
|||
|
p++;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DoesFolderExist
|
|||
|
//
|
|||
|
// Purpose: Checks if the given folder exists or not.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPTSTR lpDirName - dir name
|
|||
|
//
|
|||
|
// Returns: BOOL
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL DoesFolderExist(LPTSTR lpDirName)
|
|||
|
{
|
|||
|
DWORD dwAttribs = GetFileAttributes(lpDirName);
|
|||
|
|
|||
|
if ( dwAttribs == (DWORD) -1 )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if ( !(dwAttribs & FILE_ATTRIBUTE_DIRECTORY) )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DoesFileExist
|
|||
|
//
|
|||
|
// Purpose: Checks if the given file exists or not.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPTSTR lpFileName - file name
|
|||
|
//
|
|||
|
// Returns: BOOL
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL DoesFileExist(LPTSTR lpFileName)
|
|||
|
{
|
|||
|
DWORD dwAttribs = GetFileAttributes(lpFileName);
|
|||
|
|
|||
|
if ( dwAttribs == (DWORD) -1 )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if ( dwAttribs & FILE_ATTRIBUTE_DIRECTORY )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DoesPathExist
|
|||
|
//
|
|||
|
// Purpose: Checks if the given path exists or not. It does not pay
|
|||
|
// attention to whether it is a file or directory.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPTSTR lpPathName - path name
|
|||
|
//
|
|||
|
// Returns: BOOL
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL DoesPathExist(LPTSTR lpPathName)
|
|||
|
{
|
|||
|
DWORD dwAttribs = GetFileAttributes(lpPathName);
|
|||
|
|
|||
|
if ( dwAttribs == (DWORD) -1 )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: ILFreePriv
|
|||
|
//
|
|||
|
// Purpose: Frees an ID list that some shell apis allocate with it's own
|
|||
|
// special allocator.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// LPITEMIDLIST pidl - pointer to shell specially alloced mem
|
|||
|
//
|
|||
|
// Returns: VOID
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
VOID ILFreePriv(LPITEMIDLIST pidl)
|
|||
|
{
|
|||
|
LPMALLOC pMalloc;
|
|||
|
|
|||
|
if (pidl)
|
|||
|
{
|
|||
|
if ( NOERROR == SHGetMalloc(&pMalloc) )
|
|||
|
{
|
|||
|
pMalloc->lpVtbl->Free(pMalloc, pidl);
|
|||
|
pMalloc->lpVtbl->Release(pMalloc);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Constants used for GetOpenFileName() and GetSaveFileName() calls that
|
|||
|
// allow user to browse for an answer file.
|
|||
|
//
|
|||
|
|
|||
|
//#define TEXT_FILE_FILTER _T("Text Files (*.txt)\0*.txt\0Remote Boot Files (*.sif)\0*.sif\0Sysprep Inf Files (*.inf)\0*.inf\0All Files (*.*)\0*.*\0")
|
|||
|
#define TEXT_EXTENSION _T("txt")
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: GetAnswerFileName
|
|||
|
//
|
|||
|
// Purpose: Function for the 'Browse' button on the SaveScript page and
|
|||
|
// the NewOrEdit page.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// HWND hwnd - calling window
|
|||
|
// LPTSTR buffer - output, pass in a MAX_PATH buffer
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// BOOL - success
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL GetAnswerFileName(HWND hwnd,
|
|||
|
LPTSTR lpFileName,
|
|||
|
BOOL bSavingFile)
|
|||
|
{
|
|||
|
OPENFILENAME ofn;
|
|||
|
DWORD dwFlags;
|
|||
|
TCHAR PathBuffer[MAX_PATH];
|
|||
|
INT iRet;
|
|||
|
HRESULT hrPrintf;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// If we haven't already loaded the resource strings, then load them now.
|
|||
|
//
|
|||
|
|
|||
|
if( g_szSetupMgrFileExtensions[0] == _T('\0') )
|
|||
|
{
|
|||
|
|
|||
|
TCHAR *StrTextFiles;
|
|||
|
TCHAR *StrRemoteBootFiles;
|
|||
|
TCHAR *StrSysprepFiles;
|
|||
|
TCHAR *StrAllFiles;
|
|||
|
|
|||
|
//
|
|||
|
// Load the resource strings
|
|||
|
//
|
|||
|
|
|||
|
StrTextFiles = AllocateString(NULL, IDS_TEXT_FILES);
|
|||
|
StrRemoteBootFiles = AllocateString(NULL, IDS_REMOTE_BOOT_FILES);
|
|||
|
StrSysprepFiles = AllocateString(NULL, IDS_SYSPREP_FILES);
|
|||
|
StrAllFiles = AllocateString(NULL, IDS_ALL_FILES);
|
|||
|
|
|||
|
//
|
|||
|
// Build the text file filter string
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// The question marks (?) are just placehoders for where the NULL char
|
|||
|
// will be inserted.
|
|||
|
//
|
|||
|
|
|||
|
hrPrintf=StringCchPrintf( g_szSetupMgrFileExtensions,AS(g_szSetupMgrFileExtensions),
|
|||
|
_T("%s (*.txt)?*.txt?%s (*.sif)?*.sif?%s (*.inf)?*.inf?%s (*.*)?*.*?"),
|
|||
|
StrTextFiles,
|
|||
|
StrRemoteBootFiles,
|
|||
|
StrSysprepFiles,
|
|||
|
StrAllFiles );
|
|||
|
|
|||
|
FREE(StrTextFiles);
|
|||
|
FREE(StrRemoteBootFiles);
|
|||
|
FREE(StrSysprepFiles);
|
|||
|
FREE(StrAllFiles);
|
|||
|
|
|||
|
ConvertQuestionsToNull( g_szSetupMgrFileExtensions );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if ( bSavingFile )
|
|||
|
dwFlags = OFN_HIDEREADONLY |
|
|||
|
OFN_PATHMUSTEXIST;
|
|||
|
else
|
|||
|
dwFlags = OFN_HIDEREADONLY |
|
|||
|
OFN_FILEMUSTEXIST;
|
|||
|
|
|||
|
GetCurrentDirectory(MAX_PATH, PathBuffer);
|
|||
|
|
|||
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|||
|
ofn.hwndOwner = hwnd;
|
|||
|
ofn.hInstance = NULL;
|
|||
|
ofn.lpstrFilter = g_szSetupMgrFileExtensions;
|
|||
|
ofn.lpstrCustomFilter = NULL;
|
|||
|
ofn.nMaxCustFilter = 0L;
|
|||
|
ofn.nFilterIndex = 1;
|
|||
|
ofn.lpstrFile = lpFileName;
|
|||
|
ofn.nMaxFile = MAX_PATH;
|
|||
|
ofn.lpstrFileTitle = NULL;
|
|||
|
ofn.nMaxFileTitle = 0;
|
|||
|
ofn.lpstrInitialDir = PathBuffer;
|
|||
|
ofn.lpstrTitle = NULL;
|
|||
|
ofn.Flags = dwFlags;
|
|||
|
ofn.nFileOffset = 0;
|
|||
|
ofn.nFileExtension = 0;
|
|||
|
ofn.lpstrDefExt = TEXT_EXTENSION;
|
|||
|
|
|||
|
if ( bSavingFile )
|
|||
|
iRet = GetSaveFileName(&ofn);
|
|||
|
else
|
|||
|
iRet = GetOpenFileName(&ofn);
|
|||
|
|
|||
|
if ( ! iRet )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
MyGetFullPath(lpFileName);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: ShowBrowseFolder
|
|||
|
//
|
|||
|
// Purpose: Displays a browse folder for the user to select a file from.
|
|||
|
// Takes the headache out of making an OPENFILENAME struct and filling
|
|||
|
// it up.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// HWND hwnd - handle to the dialog box
|
|||
|
// TCHAR *szFileFilter - string to display descriptions and extensions
|
|||
|
// on the files
|
|||
|
// TCHAR *szFileExtension - string that is the default extension for the file
|
|||
|
// DWORD dwFlags - bit flags used to initialize the browse dialog
|
|||
|
// TCHAR *szStartingPath - path the browse should start at
|
|||
|
// TCHAR *szFileNameAndPath - path and filename the user selected
|
|||
|
//
|
|||
|
// Returns: Non-Zero - if user specified a file
|
|||
|
// Zero - if user did not specify a file
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
INT
|
|||
|
ShowBrowseFolder( IN HWND hwnd,
|
|||
|
IN TCHAR *szFileFilter,
|
|||
|
IN TCHAR *szFileExtension,
|
|||
|
IN DWORD dwFlags,
|
|||
|
IN TCHAR *szStartingPath,
|
|||
|
IN OUT TCHAR *szFileNameAndPath ) {
|
|||
|
|
|||
|
OPENFILENAME ofn;
|
|||
|
|
|||
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|||
|
ofn.hwndOwner = hwnd;
|
|||
|
ofn.hInstance = NULL;
|
|||
|
ofn.lpstrFilter = szFileFilter;
|
|||
|
ofn.lpstrCustomFilter = NULL;
|
|||
|
ofn.nMaxCustFilter = 0L;
|
|||
|
ofn.nFilterIndex = 1;
|
|||
|
ofn.lpstrFile = szFileNameAndPath;
|
|||
|
ofn.nMaxFile = MAX_PATH;
|
|||
|
ofn.lpstrFileTitle = NULL;
|
|||
|
ofn.nMaxFileTitle = 0;
|
|||
|
ofn.lpstrInitialDir = szStartingPath;
|
|||
|
ofn.lpstrTitle = NULL;
|
|||
|
ofn.Flags = dwFlags;
|
|||
|
ofn.nFileOffset = 0;
|
|||
|
ofn.nFileExtension = 0;
|
|||
|
ofn.lpstrDefExt = szFileExtension;
|
|||
|
|
|||
|
return( GetOpenFileName( &ofn ) );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: GetPlatform
|
|||
|
//
|
|||
|
// Purpose:
|
|||
|
//
|
|||
|
// Arguments: OUT TCHAR *pBuffer - buffer to copy the platform string to,
|
|||
|
// assumed to be able to hold MAX_PATH chars
|
|||
|
//
|
|||
|
// Returns: VOID
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
VOID
|
|||
|
GetPlatform( OUT TCHAR *pBuffer )
|
|||
|
{
|
|||
|
|
|||
|
SYSTEM_INFO SystemInfo;
|
|||
|
|
|||
|
GetSystemInfo( &SystemInfo );
|
|||
|
|
|||
|
switch( SystemInfo.wProcessorArchitecture )
|
|||
|
{
|
|||
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
|||
|
|
|||
|
lstrcpyn( pBuffer, _T("i386"), MAX_PATH );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
|||
|
|
|||
|
lstrcpyn( pBuffer, _T("amd64"), MAX_PATH );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
lstrcpyn( pBuffer, _T("i386"), MAX_PATH );
|
|||
|
|
|||
|
AssertMsg( FALSE,
|
|||
|
"Unknown Processor. Can't set sysprep language files path." );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|