//+------------------------------------------------------------------------- // // 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 #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 & xa, WCHAR const * pwsz ) { XPtrST 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; }