WindowsXP/Source/XPSP1/NT/inetsrv/query/setupqry/catcnfg.cxx
2024-08-03 16:30:48 +02:00

781 lines
22 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1998 - 2000.
//
// File: CatCnfg.cxx
//
// Contents: Support for adding catalogs during setup.
//
// History: 13-May-1998 KyleP Added copyright
//
//--------------------------------------------------------------------------
#include "pch.cxx"
#pragma hdrstop
#include <ciregkey.hxx>
#include "catcnfg.hxx"
//+-------------------------------------------------------------------------
//
// Member: CCatalogConfig::CCatalogConfig
//
// Synopsis: Constructor
//
// History: 9-10-97 mohamedn
//
//--------------------------------------------------------------------------
CCatalogConfig::CCatalogConfig(CError & Err) :
_Err( Err ),
_cDrive( 0 ),
_pwszCatalogDrive( 0 ),
_cIncludedScopes( 0 ), _xaIncludedScopes( 10 ),
_cExcludedScopes( 0 ), _xaExcludedScopes( 10 )
{
RtlZeroMemory( _DriveList, sizeof _DriveList );
}
//+-------------------------------------------------------------------------
//
// Member: CCatalogConfig::InitDriveList, public
//
// Synopsis: Initialize drive list with local drive names, types, and
// available/free space.
//
// Arguments: none
//
// Returns: ERROR_SUCCESS upon sucess,
// none zero upon failure.
//
// History: 6-27-97 mohamedn created
// 9/10/97 mohamedn rewritten catalog configuration
//
//--------------------------------------------------------------------------
BOOL CCatalogConfig::InitDriveList()
{
// 26 drive letters * 4 characters per drive + terminating NULL.
const DWORD dwSize = MAX_DRIVES * CHARS_PER_DRIVE + 1;
WCHAR wszListOfAllDrives[ dwSize ];
unsigned iDriveNumber = 0;
DWORD dwRetVal = 0;
RtlZeroMemory( wszListOfAllDrives, sizeof wszListOfAllDrives );
dwRetVal = GetLogicalDriveStrings(dwSize, wszListOfAllDrives);
if ( dwRetVal == 0 || dwRetVal > dwSize )
{
DWORD dwErr = GetLastError();
isDebugOut(( "GetLogicalDriveStrings Failed: dwRetVal: %d, GetLastError(): %d\n",
dwRetVal, dwErr ));
ISError( IS_MSG_COULD_NOT_CONFIGURE_CATALOGS, _Err, LogSevFatalError, dwErr );
return FALSE;
}
for ( WCHAR *pwszTmp = wszListOfAllDrives;
*pwszTmp;
pwszTmp += CHARS_PER_DRIVE )
{
switch (GetDriveType(pwszTmp))
{
case DRIVE_FIXED: // The disk cannot be removed from the drive.
break;
default:
isDebugOut(( "InitDriveList: Unexpected drive type %d\n",
GetDriveType(pwszTmp) ));
case 0: // The drive type cannot be determined.
case 1: // The root directory does not exist.
case DRIVE_REMOVABLE: // The media can be removed from the drive.
case DRIVE_REMOTE: // The drive is a remote (network) drive.
case DRIVE_CDROM: // drive is a CD-ROM drive.
case DRIVE_RAMDISK: // The drive is a RAM disk.
continue;
}
_DriveList[iDriveNumber].SetDriveName(pwszTmp);
if ( ! _DriveList[iDriveNumber].SetDriveInfo( ) )
{
continue;
}
else
{
iDriveNumber++;
}
}
_cDrive = iDriveNumber;
ReservePageFileData();
return ( _cDrive > 0 ? TRUE : FALSE );
}
//+-------------------------------------------------------------------------
//
// Member: CCatalogConfig::ReservePageFileData, private
//
// Synopsis: Reserve unallocated space for page files.
//
// Arguments: none
//
// Returns: TRUE upon sucess, FALSE upon failure.
//
// History: 26 Oct 1998 AlanwW Created
//
//--------------------------------------------------------------------------
const WCHAR wszPagingFileKey[] =
L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management";
const WCHAR wszPagingFileValueName[] = L"PagingFiles";
BOOL CCatalogConfig::ReservePageFileData()
{
WCHAR awcPagingFiles[2000];
awcPagingFiles[0] = L'\0';
//
// Get the original page file info from
// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessonManager
//
CWin32RegAccess reg( HKEY_LOCAL_MACHINE, wszPagingFileKey );
if ( ! reg.Get( wszPagingFileValueName,
awcPagingFiles,
sizeof awcPagingFiles/sizeof awcPagingFiles[0] ) )
return FALSE;
//
// Iterate through all paging files, reserve any difference between
// the max size and currently allocated size.
//
WCHAR * pwsz = &awcPagingFiles[0];
while ( *pwsz )
{
WCHAR *pwszPageFile = pwsz;
pwsz = wcschr(pwsz, L' ');
if ( ! pwsz )
break;
*pwsz++ = L'\0';
ULONG ulMinAlloc = _wtoi( pwsz );
WCHAR *pwsz2 = wcschr(pwsz, L' ');
ULONG ulMaxAlloc = ulMinAlloc + MAXOVERMINFACTOR;
if ( pwsz2 )
ulMaxAlloc = _wtoi( pwsz2 );
while ( *pwsz )
pwsz++;
pwsz++;
CDriveInformation * pDriveInfo = GetDriveInfo( pwszPageFile );
if ( !pDriveInfo )
continue;
//
// For some reason, GetFileAttributesEx will get a sharing violation
// on an open paging file. FindFirstFile will work to get the very
// same information.
//
HANDLE hFind;
WIN32_FIND_DATA FindData;
if ( (hFind = FindFirstFile(pwszPageFile, &FindData)) ==
INVALID_HANDLE_VALUE )
{
isDebugOut(( "ReservePageFileData: FindFirstFile %ws failed: %x\n",
pwszPageFile,
GetLastError() ));
continue;
}
FindClose(hFind);
ULARGE_INTEGER ullFileSize;
ullFileSize.LowPart = FindData.nFileSizeLow;
ullFileSize.HighPart = FindData.nFileSizeHigh;
pDriveInfo->ReservePagingData( ulMaxAlloc * ONE_MB,
ullFileSize.QuadPart );
}
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Member: CDriveInformation::GetDriveInfo, public
//
// Synopsis: Returns pointer to drive information structure.
//
// Arguments: [pwszPath] - path name to be looked up
//
// Returns: CDriveInformation* - pointer to drive information; 0 if not found
//
// History: 29 Oct 1998 AlanW Created
//
//--------------------------------------------------------------------------
CDriveInformation * CCatalogConfig::GetDriveInfo(WCHAR const * pwszPath)
{
WCHAR wcDriveLetter = (WCHAR)toupper( *pwszPath );
for (unsigned i = 0; i < _cDrive; i++ )
{
if (toupper( _DriveList[i].GetDriveLetter() ) == wcDriveLetter )
return &_DriveList[i];
}
return 0;
}
//+-------------------------------------------------------------------------
//
// Member: CDriveInformation::SetDriveInfo, public
//
// Synopsis: Obtains drive info
//
// Arguments: [none]
//
// Returns: TRUE upon success, False upon failure.
//
// History: 6-27-97 mohamedn created
// 26 Oct 1998 AlanwW Enhanced and made a CDriveInfo method.
//
//--------------------------------------------------------------------------
static WCHAR pwszBootFile1[] = L"x:\\NTLDR"; // x86
static WCHAR pwszBootFile2[] = L"x:\\OS\\WINNT50\\OSLOADER.EXE"; // risc
static WCHAR * apwszBootFiles[] = {
pwszBootFile1,
pwszBootFile2,
};
BOOL CDriveInformation::SetDriveInfo()
{
Win4Assert( 0 != GetDriveLetter() );
_cbFreeSpace = _cbTotalSpace = _cbReservedSpace = 0;
ULARGE_INTEGER cbFreeBytesToCaller;
ULARGE_INTEGER cbTotalNumberOfBytes;
ULARGE_INTEGER cbTotalNumberOfFreeBytes;
cbFreeBytesToCaller.QuadPart = 0;
cbTotalNumberOfBytes.QuadPart = 0;
cbTotalNumberOfFreeBytes.QuadPart = 0;
//
// returns 0 upon failure, none-zero upon success.
//
BOOL fSuccess = GetDiskFreeSpaceEx( _wszDriveName,
&cbFreeBytesToCaller,
&cbTotalNumberOfBytes,
&cbTotalNumberOfFreeBytes );
if (!fSuccess)
{
isDebugOut(( "SetDriveInfo: GetDiskFreeSapceEx %ws failed: %x\n",
_wszDriveName,
GetLastError() ));
return fSuccess;
}
_cbFreeSpace= cbTotalNumberOfFreeBytes.QuadPart;
_cbTotalSpace= cbTotalNumberOfBytes.QuadPart;
//
// Determine if the volume supports security (i.e., if it's NTFS)
//
fSuccess = GetVolumeInformationW( _wszDriveName,
0, 0, // volume name
0, // volume serial number
0, // max filename length
&_dwFileSystemFlags,
0, 0 ); // file system name
if (!fSuccess)
{
isDebugOut(( "SetDriveInfo: GetFileSystemInfo failed: %x\n",GetLastError() ));
return fSuccess;
}
for (unsigned i=0; i < NUMELEM( apwszBootFiles ); i++)
{
if (Exists(apwszBootFiles[i]))
{
_fIsBootDrive = TRUE;
break;
}
}
return fSuccess;
}
//+-------------------------------------------------------------------------
//
// Member: CDriveInformation::Exists, public
//
// Synopsis: Determines if a file or directory exists
//
// Arguments: [pwszPath] - path name of the file to check
//
// Notes: The [pwszPath] must be a full path name starting with a
// drive letter. The drive letter is overwritten by this
// method.
//
// Returns: TRUE if the file exists, FALSE upon failure or non-existance.
//
// History: 26 Oct 1998 AlanW Created
//
//--------------------------------------------------------------------------
BOOL CDriveInformation::Exists(WCHAR * pwszPath)
{
*pwszPath = GetDriveLetter();
DWORD attr = GetFileAttributes( pwszPath );
// If we couldn't determine file's attributes, don't consider it found
// unless the error code indirectly indicates that it exists.
if ( 0xffffffff == attr )
{
isDebugOut(( DEB_TRACE, "Exists: GetFileAttributes( %ws ) Failed: %d\n",
pwszPath, GetLastError() ));
if (GetLastError() == ERROR_SHARING_VIOLATION)
return TRUE; // It must exist
return FALSE;
}
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Member: CCatalogConfig::ConfigureDefaultCatalog
//
// Synopsis: Creates a single default catalog if sufficient disk space
// exists on one drive.
//
// Arguments: [wszPrimaryScope] -- Path name of primary indexed directory
//
// Returns: TRUE upon success, FALSE upon Failure,
//
// History: 9-10-97 mohamedn
//
//--------------------------------------------------------------------------
static WCHAR wszUpgradeDir[] = L"x:\\$WIN_NT$.~LS";
BOOL CCatalogConfig::ConfigureDefaultCatalog(
WCHAR const * pwszPrimaryScope )
{
{
//
// Reserve space for a net upgrade of the OS if we're not currently
// doing one (in which case the space for it will already be in use).
// Because we will preferably use an NTFS drive for the catalog, try
// using a FAT drive for the upgrade files.
//
int iUpgradeFiles = -1;
int iBestFitForUpgrade = -1;
ULONGLONG cbBestFitForUpgrade = 0;
BOOL fBestFitOnNtfs = FALSE;
for ( unsigned i = 0 ; i < _cDrive; i++ )
{
if ( iUpgradeFiles == -1 && _DriveList[i].Exists( wszUpgradeDir ) )
{
iUpgradeFiles = i;
break;
}
ULONGLONG cbAvail = _DriveList[i].GetAvailableSpace();
if ( cbAvail < MIN_UPGRADE_SPACE )
continue;
if ( iBestFitForUpgrade == -1 ||
( cbAvail < cbBestFitForUpgrade && fBestFitOnNtfs ) ||
( ! _DriveList[i].IsNtfs() && fBestFitOnNtfs ) )
{
cbBestFitForUpgrade = cbAvail;
iBestFitForUpgrade = i;
fBestFitOnNtfs = _DriveList[i].IsNtfs();
}
}
if ( iUpgradeFiles == -1 && iBestFitForUpgrade != -1 )
_DriveList[iBestFitForUpgrade].AddReservedSpace( MIN_UPGRADE_SPACE );
else if ( iUpgradeFiles == -1 )
{
isDebugOut(( DEB_TRACE, "Not enough room for net upgrade!\n" ));
return FALSE;
}
}
//
// Determine which drive to put the catalog on.
//
int iBiggestFreeNTFS = -1;
int iBiggestFreeFAT = -1;
ULONGLONG cbMaxFreeSpaceOnNTFS = 0;
ULONGLONG cbMaxFreeSpaceOnFAT = 0;
for ( unsigned i = 0 ; i < _cDrive; i++ )
{
if ( _DriveList[i].IsSmallBootPartition() )
continue;
int * piBiggestFree = &iBiggestFreeFAT;
ULONGLONG * pcbMaxFree = &cbMaxFreeSpaceOnFAT;
if ( _DriveList[i].IsNtfs() )
{
piBiggestFree = &iBiggestFreeNTFS;
pcbMaxFree = &cbMaxFreeSpaceOnNTFS;
}
if ( *pcbMaxFree < _DriveList[i].GetAvailableSpace() )
{
*pcbMaxFree = _DriveList[i].GetAvailableSpace();
*piBiggestFree = i;
}
}
BOOL fAddNtfsDrives = FALSE;
CDriveInformation * pCatalogDrive = 0;
double dblCatalogSizeRatio;
if ( iBiggestFreeNTFS != -1 )
{
//
// There is an NTFS drive on the system; need to put the catalog
// there.
//
pCatalogDrive = &_DriveList[iBiggestFreeNTFS];
dblCatalogSizeRatio = CATALOG_SIZE_RATIO_NTFS;
fAddNtfsDrives = TRUE;
}
else if ( iBiggestFreeFAT != -1 )
{
pCatalogDrive = &_DriveList[iBiggestFreeFAT];
dblCatalogSizeRatio = CATALOG_SIZE_RATIO_FAT;
fAddNtfsDrives = FALSE;
}
if ( 0 == pCatalogDrive ||
pCatalogDrive->GetAvailableSpace() < MIN_CATALOG_SPACE )
{
isDebugOut(( DEB_TRACE, "Not enough room for minimal catalog!\n" ));
return FALSE;
}
_pwszCatalogDrive = pCatalogDrive->GetDriveName();
pCatalogDrive->AddReservedSpace( MIN_CATALOG_SPACE );
// Add the primary scope directory for the catalog.
if ( pwszPrimaryScope && *pwszPrimaryScope )
AddIncludedDir( pwszPrimaryScope );
//
// Iterate through the list of drives once or twice, depending on
// whether all drives are FAT.
//
unsigned maxLoop = _cDrive * ( (fAddNtfsDrives == TRUE) + 1);
for ( i = 0 ; i < maxLoop; i++ )
{
// If end of NTFS enumeration, go back around the loop for FAT drives.
if (i == _cDrive)
fAddNtfsDrives = FALSE;
CDriveInformation & DriveToCheck = _DriveList[i % _cDrive];
if ( DriveToCheck.IsSmallBootPartition() )
continue;
if ( DriveToCheck.IsNtfs() != fAddNtfsDrives )
continue;
ULONGLONG cbUsed = DriveToCheck.GetUsedSpace();
cbUsed = (ULONGLONG) ((LONGLONG)cbUsed * dblCatalogSizeRatio);
if ( cbUsed < pCatalogDrive->GetAvailableSpace() )
{
AddIncludedDir( DriveToCheck.GetDriveName() );
pCatalogDrive->AddReservedSpace( cbUsed );
}
}
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Member: CCatalogConfig::SaveState
//
// Synopsis: Saves the state of the catalog configuration in the registry.
//
// Arguments: - NONE -
//
// Returns: TRUE upon success, FALSE upon Failure,
//
// History: 19 Nov 1998 AlanW Created
//
//--------------------------------------------------------------------------
BOOL CCatalogConfig::SaveState( )
{
Win4Assert( 0 != GetName() && 0 != GetLocation() );
CCatReg catReg(_Err);
if ( !catReg.Init( GetName(), GetLocation() ) )
return FALSE;
//
// Add all the included scopes
//
WCHAR const * pwszScope;
for (unsigned i = 0; pwszScope = GetIncludedScope( i ); i++)
{
if ( !catReg.AddScope( pwszScope, L",,5" ) )
{
return FALSE;
}
}
//
// Now add the excluded scopes
//
for (i = 0; pwszScope = GetExcludedScope( i ); i++)
{
if ( !catReg.AddScope( pwszScope, L",,4" ) )
{
return FALSE;
}
}
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Member: CCatalogConfig::AddStringToArray, private static
//
// Synopsis: Adds a string to an XArray
//
// Arguments: [c] - current count of strings in array
// [xa] - the XArray of strings
// [pwsz] - string to be added
//
// Returns: BOOL - FALSE if any problems, TRUE otherwise
//
// Notes: Can throw on allocation failures.
//
// History: 04 Nov 1998 AlanW Created
//
//--------------------------------------------------------------------------
BOOL CCatalogConfig::AddStringToArray(
ULONG & c,
XArray<WCHAR const *> & xa,
WCHAR const * pwsz )
{
XPtrST<WCHAR> xpwsz;
if (pwsz)
{
WCHAR * pwszCopy = new WCHAR[ wcslen(pwsz) + 1 ];
xpwsz.Set(pwszCopy);
wcscpy( pwszCopy, pwsz );
pwsz = pwszCopy;
}
if ( c >= xa.Count() )
xa.ReSize( c*2 );
xa[c] = pwsz;
c++;
xpwsz.Acquire();
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Member: CCatReg::Init
//
// Synopsis: Initializes catalog registry key configurator
//
// Arguments: [ pwszCatName ] - catalog name
// [ pwszLocation] - catalog location
//
// Returns: none - throws upon fatal errors.
//
// History: 9-10-97 mohamedn
//
//--------------------------------------------------------------------------
BOOL CCatReg::Init( WCHAR const *pwszCatName, WCHAR const *pwszLocation)
{
ISAssert( pwszCatName );
// create a catalog for the drive
BOOL fExisted = FALSE;
CWin32RegAccess reg( HKEY_LOCAL_MACHINE, wcsRegCatalogsSubKey );
if ( !reg.CreateKey( pwszCatName, fExisted ) )
{
DWORD dwErr = GetLastError();
isDebugOut(( "created catalogs\\%ws subkey Failed: %d\n",
pwszCatName, dwErr ));
ISError( IS_MSG_COULD_NOT_CONFIGURE_CATALOGS, _Err, LogSevFatalError, dwErr );
return FALSE;
}
isDebugOut(( DEB_TRACE, "created catalogs\\%ws subkey\n", pwszCatName ));
wcscpy( _wszCatRegSubKey, wcsRegCatalogsSubKey );
wcscat( _wszCatRegSubKey, L"\\" );
wcscat( _wszCatRegSubKey, pwszCatName );
CWin32RegAccess regSystem( reg.GetHKey(), pwszCatName );
if ( !regSystem.Set( L"Location", pwszLocation ) )
{
DWORD dw = GetLastError();
isDebugOut(( "Failed to set Cat Location valued:%ws, %d\n",
pwszLocation, dw ));
ISError( IS_MSG_COULD_NOT_CONFIGURE_CATALOGS, _Err, LogSevFatalError, dw );
return FALSE;
}
if ( !regSystem.Set( wcsIsIndexingW3Roots, (DWORD) 0 ) ||
!regSystem.Set( wcsIsIndexingNNTPRoots, (DWORD) 0 )
)
{
DWORD dw = GetLastError();
isDebugOut(( "Failed to set Cat values: %d\n", dw ));
ISError( IS_MSG_COULD_NOT_CONFIGURE_CATALOGS, _Err, LogSevFatalError, dw );
return FALSE;
}
// Create a "Scopes" key so a watch can be established in cicat
// It needs no entries.
if ( !regSystem.CreateKey( wcsCatalogScopes, fExisted ) )
{
DWORD dw = GetLastError();
isDebugOut(( "created scopes subkey Failed: %d\n", dw ));
ISError( IS_MSG_COULD_NOT_CONFIGURE_CATALOGS, _Err, LogSevFatalError, dw );
return FALSE;
}
//
// initialize the reg scopes subkey name
//
wcscpy( _wszCatScopeRegSubKey, _wszCatRegSubKey );
wcscat( _wszCatScopeRegSubKey, L"\\" );
wcscat( _wszCatScopeRegSubKey, wcsCatalogScopes );
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Member: CCatReg::AddScope
//
// Synopsis: Adds a scope for the current catalog
//
// Arguments: [ pwszScopeName ] - scope name
// [ pwszScopeAttrib] - scope attributes
//
// Returns: none - throws upon fatal errors.
//
// History: 9-10-97 mohamedn
//
//--------------------------------------------------------------------------
BOOL CCatReg::AddScope( WCHAR const * pwszScopeName,
WCHAR const * pwszScopeAttrib )
{
CWin32RegAccess regScopes( HKEY_LOCAL_MACHINE, _wszCatScopeRegSubKey );
if ( !regScopes.Set( pwszScopeName, pwszScopeAttrib ) )
{
DWORD dwRetVal = GetLastError();
isDebugOut(( "Failed to set scope value:\\%ws, %d\n",
pwszScopeName, dwRetVal ));
ISError( IS_MSG_COULD_NOT_CONFIGURE_CATALOGS, _Err, LogSevFatalError, dwRetVal );
return FALSE;
}
else
{
return TRUE;
}
}
//+-------------------------------------------------------------------------
//
// Member: CCatReg::TrackW3Svc, public
//
// Synopsis: Configures catalog to be a 'web' catalog.
//
// Arguments: [dwInstance] -- WWW Virtual Server instance number
//
// Returns: TRUE if setup succeeded.
//
// History: 13-May-1998 KyleP Created
//
//--------------------------------------------------------------------------
BOOL CCatReg::TrackW3Svc( DWORD dwInstance )
{
CWin32RegAccess regSystem( HKEY_LOCAL_MACHINE, _wszCatRegSubKey );
// Fix for 249655. For a web catalog, wcsGenerateCharacterization and
// wcsFilterFilesWithUnknownExtensions should be set as follows.
if ( !regSystem.Set( wcsIsIndexingW3Roots, 1 ) ||
!regSystem.Set( wcsW3SvcInstance, dwInstance ) ||
!regSystem.Set( wcsGenerateCharacterization, 1 ) ||
!regSystem.Set( wcsFilterFilesWithUnknownExtensions, (DWORD)0 ) ||
!regSystem.Set( wcsMaxCharacterization, 320 ) )
{
DWORD dw = GetLastError();
isDebugOut(( "Failed to set Cat values: %d\n", dw ));
ISError( IS_MSG_COULD_NOT_CONFIGURE_CATALOGS, _Err, LogSevFatalError, dw );
return FALSE;
}
return TRUE;
}