|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 2001.
//
// File: ida.cxx
//
// Contents: Parser for an IDQ file
//
// History: 96/Jan/3 DwightKr Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <fsciexps.hxx>
//
// Constants
//
static WCHAR const wcsPRootVar[] = L"PROOT_"; unsigned const ccPRootVar = sizeof(wcsPRootVar)/sizeof(WCHAR) - 1;
static WCHAR const wcsIndexVar[] = L"INDEX_"; unsigned const ccIndexVar = sizeof(wcsIndexVar)/sizeof(WCHAR) - 1;
static WCHAR const wcsNNTP[] = L"NNTP_"; unsigned const ccNNTP = sizeof(wcsNNTP)/sizeof(WCHAR) - 1;
static WCHAR const wcsIMAP[] = L"IMAP_"; unsigned const ccIMAP = sizeof(wcsIMAP)/sizeof(WCHAR) - 1;
static WCHAR const wcsScanVar[] = L"SCAN_"; unsigned const ccScanVar = sizeof(wcsScanVar)/sizeof(WCHAR) - 1;
unsigned const ccStringizedGuid = 36;
BOOL ParseGuid( WCHAR const * pwcsGuid, GUID & guid );
//+---------------------------------------------------------------------------
//
// Member: CIDAFile::CIDAFile - public constructor
//
// Synopsis: Builds a CIDAFile object, initializes values
//
// Arguments: [wcsFileName] -- full path to IDQ file
//
// History: 13-Apr-96 KyleP Created.
//
//----------------------------------------------------------------------------
CIDAFile::CIDAFile( WCHAR const * wcsFileName, UINT codePage ) : _eOperation( CIDAFile::CiState ), _wcsCatalog(0), _wcsHTXFileName( 0 ), _wcsLocale(0), _cReplaceableParameters(0), _refCount(0), _codePage(codePage) { ULONG cwc = wcslen(wcsFileName);
if ( cwc >= sizeof(_wcsIDAFileName)/sizeof(WCHAR) ) { ciGibDebugOut(( DEB_WARN, "Too long a path (%ws)\n", wcsFileName )); THROW( CException( STATUS_INVALID_PARAMETER )); }
RtlCopyMemory( _wcsIDAFileName, wcsFileName, (cwc+1) * sizeof(WCHAR) ); }
//+---------------------------------------------------------------------------
//
// Member: CIDAFile::~CIDAFile - public destructor
//
// History: 13-Apr-96 KyleP Created.
//
//----------------------------------------------------------------------------
CIDAFile::~CIDAFile() { Win4Assert( _refCount == 0 );
delete [] _wcsCatalog; delete [] _wcsHTXFileName; delete [] _wcsLocale; }
//+---------------------------------------------------------------------------
//
// Member: CIDAFile::ParseFile, private
//
// Synopsis: Parses the given file and sets up the necessary variables
//
// History: 13-Apr-96 KyleP Created.
// 23-Jul-96 DwightKr Use mapped file I/O which checks
// ACLs and throws ACCESS_DENIED if
// not available.
//
//----------------------------------------------------------------------------
void CIDAFile::ParseFile() { //
// Parse the query parameters
//
XPtr<CFileMapView> xMapView;
TRY { xMapView.Set( new CFileMapView( _wcsIDAFileName ) ); xMapView->Init(); } CATCH( CException, e ) { if ( HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) == e.GetErrorCode() ) { THROW( CIDQException( MSG_CI_IDQ_NOT_FOUND, 0 ) ); } else { RETHROW(); } } END_CATCH
CFileBuffer idaFile( xMapView.GetReference(), _codePage );
//
// Process a line at a time, look for the [Admin] section and
// process lines within that section.
//
BOOL fAdminSection = FALSE; int iLine = 0; // Start counting at line #1
for( ;; ) { iLine++; XGrowable<WCHAR> xLine;
ULONG cwcChar = idaFile.fgetsw( xLine );
if( 0 == cwcChar ) { break; }
WCHAR *pwcLine = xLine.Get();
//
// Skip ahead until we find a [Admin] section
//
if ( L'[' == *pwcLine ) { if ( _wcsnicmp(pwcLine+1, L"Admin]", 6) == 0 ) fAdminSection = TRUE; else fAdminSection = FALSE;
continue; }
//
// Ignore comments.
//
else if ( L'#' == *pwcLine ) continue;
if ( fAdminSection ) { CQueryScanner scanner( pwcLine, FALSE ); ParseOneLine( scanner, iLine ); } }
//
// Verify that the minimum set of parameters are specified.
//
//
// We must have all of the following:
//
// - a HTX file name
//
if ( 0 == _wcsHTXFileName ) { // Report an error
ciGibDebugOut(( DEB_IERROR, "Template not found in IDA file.\n" )); THROW( CIDQException(MSG_CI_IDQ_MISSING_TEMPLATEFILE, 0) ); }
//
// If no catalog was specified, use the default catalog in the registry
//
if ( 0 == _wcsCatalog ) { ciGibDebugOut(( DEB_ITRACE, "Using default catalog\n" ));
WCHAR awcTmp[ MAX_PATH ]; ULONG cwcRequired = TheIDQRegParams.GetISDefaultCatalog( awcTmp, MAX_PATH ); if ( cwcRequired > MAX_PATH ) THROW( CException(STATUS_INVALID_PARAMETER) );
cwcRequired++; // make room for termination
_wcsCatalog = new WCHAR[ cwcRequired ]; RtlCopyMemory( _wcsCatalog, awcTmp, cwcRequired * sizeof WCHAR ); }
}
//+---------------------------------------------------------------------------
//
// Member: CIDAFile::ParseOneLine, private
//
// Synopsis: Parses one line of the IDQ file
//
// Arguments: [scan] -- scanner initialized with the current line
// [iLine] -- current line number
//
// History: 13-Apr-96 KyleP Created.
//
//----------------------------------------------------------------------------
void CIDAFile::ParseOneLine( CQueryScanner & scan, unsigned iLine ) { //
// Is this a comment line (does it start with #) or an empty line?
//
if ( scan.LookAhead() == PROP_REGEX_TOKEN || scan.LookAhead() == EOS_TOKEN ) { return; }
if ( scan.LookAhead() != TEXT_TOKEN ) // Better be a word
{ // Report an error
THROW( CIDQException( MSG_CI_IDQ_EXPECTING_NAME, iLine ) ); }
XPtrST<WCHAR> wcsAttribute( scan.AcqWord() );
if( wcsAttribute.GetPointer() == 0 ) // Better find a word
{ THROW( CIDQException( MSG_CI_IDQ_EXPECTING_TYPE, iLine ) ); }
scan.Accept();
if ( scan.LookAhead() != EQUAL_TOKEN ) { // Report an error
THROW( CIDQException( MSG_CI_IDQ_EXPECTING_EQUAL, iLine ) ); }
scan.Accept();
if ( 0 == _wcsicmp( wcsAttribute.GetPointer(), ISAPI_CI_CATALOG ) ) GetStringValue( scan, iLine, &_wcsCatalog ); else if ( 0 == _wcsicmp( wcsAttribute.GetPointer(), ISAPI_CI_TEMPLATE ) ) GetStringValue( scan, iLine, &_wcsHTXFileName ); else if ( 0 == _wcsicmp( wcsAttribute.GetPointer(), ISAPI_CI_ADMIN_OPERATION ) ) { WCHAR * pwcsTemp = 0; GetStringValue( scan, iLine, &pwcsTemp );
XPtrST<WCHAR> xwcsTemp( pwcsTemp );
if ( 0 == pwcsTemp ) { THROW( CIDQException( MSG_CI_IDA_INVALID_OPERATION, iLine ) ); } else if ( 0 == _wcsicmp( pwcsTemp, wcsOpGetState ) ) _eOperation = CIDAFile::CiState; else if ( 0 == _wcsicmp( pwcsTemp, wcsOpForceMerge ) ) _eOperation = CIDAFile::ForceMerge; else if ( 0 == _wcsicmp( pwcsTemp, wcsOpScanRoots ) ) _eOperation = CIDAFile::ScanRoots; else if ( 0 == _wcsicmp( pwcsTemp, wcsOpUpdateCache ) ) _eOperation = CIDAFile::UpdateCache; else { THROW( CIDQException( MSG_CI_IDA_INVALID_OPERATION, iLine ) ); } } else if ( 0 == _wcsicmp( wcsAttribute.GetPointer(), ISAPI_CI_LOCALE ) ) { GetStringValue( scan, iLine, &_wcsLocale ); } else { //
// We've found a keyword/attribute that we don't support.
// Don't report an error. This will allow this version of the
// parser to work with newer .IDA file versions with new parameters.
//
ciGibDebugOut(( DEB_ERROR, "Invalid string in IDQ file: %ws\n", wcsAttribute.GetPointer() )); } }
//+---------------------------------------------------------------------------
//
// Member: CIDAFile::GetStringValue - private
//
// Synopsis: Gets the string value on the currenct line
//
// Arguments: [scan] -- scanner initialized with the current line
// [iLine] -- current line number
// [pwcsStringValue] -- value to put string into
//
// History: 13-Apr-96 KyleP Created.
//
//----------------------------------------------------------------------------
void CIDAFile::GetStringValue( CQueryScanner & scan, unsigned iLine, WCHAR ** pwcsStringValue ) { if ( 0 != *pwcsStringValue ) { ciGibDebugOut(( DEB_IWARN, "Duplicate CiXX=value in IDA file on line #%d\n", iLine )); THROW( CIDQException(MSG_CI_IDQ_DUPLICATE_ENTRY, iLine) ); }
*pwcsStringValue = scan.AcqLine();
if ( IsAReplaceableParameter( *pwcsStringValue ) != eIsSimpleString ) { _cReplaceableParameters++; } }
//+---------------------------------------------------------------------------
//
// Function: FindEntry, public
//
// Synopsis: Helper function for admin variable parsing.
//
// Arguments: [pwcsName] -- Variable name
// [fScan] -- TRUE for SCAN, FALSE for INDEX
// [pwcsBuf] -- Buffer for search token
//
// History: 10-Oct-96 KyleP Created.
//
//----------------------------------------------------------------------------
BOOL FindEntry( WCHAR const * * ppwcsName, BOOL fScan, WCHAR * pwcsBuf ) { if ( 0 != _wcsnicmp( *ppwcsName, wcsPRootVar, ccPRootVar ) ) return FALSE;
//
// Scan or Index?
//
WCHAR const * pwcsOutputTag; unsigned ccOutputTag;
if ( fScan ) { pwcsOutputTag = wcsScanVar; ccOutputTag = ccScanVar; } else { pwcsOutputTag = wcsIndexVar; ccOutputTag = ccIndexVar; }
//
// IMAP, NNTP or W3?
//
unsigned ccPrefix = ccOutputTag;
BOOL fW3 = FALSE; BOOL fNNTP = FALSE; BOOL fIMAP = FALSE;
if ( 0 == _wcsnicmp( *ppwcsName + ccPRootVar, wcsNNTP, ccNNTP ) ) { fNNTP = TRUE; *ppwcsName += ccNNTP; ccPrefix += ccNNTP; } else if ( 0 == _wcsnicmp( *ppwcsName + ccPRootVar, wcsIMAP, ccIMAP ) ) { fIMAP = TRUE; *ppwcsName += ccIMAP; ccPrefix += ccIMAP; } else { fW3 = TRUE; }
*ppwcsName += ccPRootVar;
//
// Length check.
//
unsigned ccName = wcslen( *ppwcsName ) + 1;
if ( ccName + ccPrefix > (MAX_PATH + ccIndexVar + ccNNTP + 1) ) { ciGibDebugOut(( DEB_WARN, "Path %ws too long for admin\n", *ppwcsName )); return FALSE; }
if ( ccName + ccPrefix > (MAX_PATH + ccIndexVar + ccIMAP + 1) ) { ciGibDebugOut(( DEB_WARN, "Path %ws too long for admin\n", *ppwcsName )); return FALSE; }
//
// Build output name
//
RtlCopyMemory( pwcsBuf, pwcsOutputTag, ccOutputTag * sizeof(WCHAR) );
if ( fNNTP ) RtlCopyMemory( pwcsBuf + ccOutputTag, wcsNNTP, ccNNTP * sizeof(WCHAR) ); else if ( fIMAP ) RtlCopyMemory( pwcsBuf + ccOutputTag, wcsIMAP, ccIMAP * sizeof(WCHAR) );
RtlCopyMemory( pwcsBuf + ccPrefix, *ppwcsName, ccName * sizeof(WCHAR) );
return TRUE; }
//+---------------------------------------------------------------------------
//
// Function: DoAdmin, public
//
// Synopsis: Executes an administrative change.
//
// Arguments: [wcsIDAFile] -- Virtual path to .IDA file
// [VarSet] -- Query variables
// [OutputFormat] -- Output format
// [vsResults] -- On success (non exception) result page
// written here.
//
// History: 13-Apr-96 KyleP Created.
// 22-Jul-96 DwightKr Make CiLocale replaceable & visible
// in HTX files
// 11-Jun-97 KyleP Use web server in Output Format
//
//----------------------------------------------------------------------------
void DoAdmin( WCHAR const * wcsIDAFile, CVariableSet & VarSet, COutputFormat & OutputFormat, CVirtualString & vsResults ) { //
// Parse .IDA file. We don't bother to cache these.
//
XPtr<CIDAFile> xIDAFile( new CIDAFile(wcsIDAFile, OutputFormat.CodePage()) ); xIDAFile->ParseFile();
ULONG cwcOut; XPtrST<WCHAR> wcsLocaleID( ReplaceParameters( xIDAFile->GetLocale(), VarSet, OutputFormat, cwcOut ) );
XArray<WCHAR> wcsLocale; LCID locale = GetQueryLocale( wcsLocaleID.GetPointer(), VarSet, OutputFormat, wcsLocale );
if ( OutputFormat.GetLCID() != locale ) {
ciGibDebugOut(( DEB_ITRACE, "Wrong codePage used for loading IDA file, used 0x%x retrying with 0x%x\n", OutputFormat.CodePage(), LocaleToCodepage(locale) ));
//
// We've parsed the IDA file with the wrong locale.
//
delete xIDAFile.Acquire();
OutputFormat.LoadNumberFormatInfo( locale );
xIDAFile.Set( new CIDAFile(wcsIDAFile, OutputFormat.CodePage()) ); xIDAFile->ParseFile(); }
SetupDefaultCiVariables( VarSet ); SetupDefaultISAPIVariables( VarSet ); SetCGIVariables( VarSet, OutputFormat );
//
// Get the catalog.
//
XPtrST<WCHAR> wcsCiCatalog( ReplaceParameters( xIDAFile->GetCatalog(), VarSet, OutputFormat, cwcOut ) );
//
// Verify that the wcsCatalog is valid
//
if ( !IsAValidCatalog( wcsCiCatalog.GetPointer(), cwcOut ) ) { THROW( CIDQException(MSG_CI_IDQ_NO_SUCH_CATALOG, 0) ); }
//
// Get the catalog and machine from the URL style catalog.
//
XPtrST<WCHAR> wcsMachine( 0 ); XPtrST<WCHAR> wcsCatalog( 0 ); SCODE sc = ParseCatalogURL( wcsCiCatalog.GetPointer(), wcsCatalog, wcsMachine );
if (FAILED(sc)) { THROW( CException(sc) ); }
Win4Assert ( 0 != wcsMachine.GetPointer() );
//
// Check that the client is allowed to perform administration
//
CheckAdminSecurity( wcsMachine.GetPointer() );
//
// Build the HTX page for [success] output
//
XPtrST<WCHAR> wcsTemplate( ReplaceParameters( xIDAFile->GetHTXFileName(), VarSet, OutputFormat, cwcOut ) );
WCHAR wcsPhysicalName[_MAX_PATH];
if ( OutputFormat.IsValid() ) { OutputFormat.GetPhysicalPath( wcsTemplate.GetPointer(), wcsPhysicalName, _MAX_PATH ); } else { if ( !GetFullPathName( wcsTemplate.GetPointer(), MAX_PATH, wcsPhysicalName, 0 ) ) { THROW( CException() ); } }
//
// Note: Parsing of HTX file needs to be done in different locations
// to ensure variables added to variable set by admin operations
// are added before parse. But we also don't want to fail the
// parse *after* doing a dangerous operation (like force merge).
//
CSecurityIdentity securityStub;
CHTXFile SuccessHTX( wcsTemplate, OutputFormat.CodePage(), securityStub, OutputFormat.GetServerInstance() );
switch ( xIDAFile->Operation() ) {
case CIDAFile::ScanRoots: { SuccessHTX.ParseFile( wcsPhysicalName, VarSet, OutputFormat );
if ( SuccessHTX.DoesDetailSectionExist() ) { THROW( CIDQException(MSG_CI_IDA_TEMPLATE_DETAIL_SECTION, 0) ); }
//
// Execute the changes. 'Entries' have the following format:
// Variable: P<virtual root> = physical root for <virtual root>
// Variable: S<virtual root> = "on" / existence means root is scanned
// Variable: T<virtual root> = "on" / existence means full scan
//
CVariableSetIter iter( VarSet );
while ( !iter.AtEnd() ) { CVariable * pVar = iter.Get(); WCHAR const * pwcsName = pVar->GetName();
WCHAR wcsScanName[MAX_PATH + ccScanVar + __max( ccNNTP, ccIMAP ) + 10 ];
if ( FindEntry( &pwcsName, // Starting variable
TRUE, // SCAN
wcsScanName )) // Matching search string returned here
{ PROPVARIANT * ppvPRoot = pVar->GetValue();
CVariable * pScanVar = VarSet.Find( wcsScanName );
if ( 0 != pScanVar ) { WCHAR const * pwszScanType = pScanVar->GetStringValueRAW();
if ( 0 != pwszScanType && ( 0 == _wcsicmp( pwszScanType, L"FullScan" ) || 0 == _wcsicmp( pwszScanType, L"IncrementalScan") ) ) { BOOL fFull = (0 == _wcsicmp( pwszScanType, L"FullScan" )); SCODE sc = UpdateContentIndex( ppvPRoot->pwszVal, wcsCatalog.GetPointer(), wcsMachine.GetPointer(), fFull ); if ( FAILED(sc) ) { ciGibDebugOut(( DEB_ERROR, "Error 0x%x scanning virtual scope %ws\n", pwcsName )); THROW( CException( sc ) ); }
} } }
iter.Next(); } break; }
case CIDAFile::UpdateCache: { SuccessHTX.ParseFile( wcsPhysicalName, VarSet, OutputFormat );
if ( SuccessHTX.DoesDetailSectionExist() ) { THROW( CIDQException(MSG_CI_IDA_TEMPLATE_DETAIL_SECTION, 0) ); }
//
// Execute the changes. 'Entries' have the following format:
// Variable: CACHESIZE_<guid>_NAME_<name> = Size for named entry
// Variable: CACHESIZE_<guid>_PROPID_<propid> = Size for numbered entry
// Variable: CACHETYPE_<guid>_NAME_<name> = Type for named entry
// Variable: CACHETYPE_<guid>_PROPID_<propid> = Type for numbered entry
//
CVariableSetIter iter( VarSet );
BOOL fSawOne = FALSE; ULONG_PTR ulToken;
SCODE sc = BeginCacheTransaction( &ulToken, wcsCatalog.GetPointer(), wcsCatalog.GetPointer(), wcsMachine.GetPointer() );
if ( FAILED(sc) ) { ciGibDebugOut(( DEB_ERROR, "Error 0x%x setting up cache transaction.\n", sc )); THROW( CException( sc ) ); }
while ( !iter.AtEnd() ) { CVariable * pVar = iter.Get(); WCHAR const * pwcsName = pVar->GetName();
//
// We write out last prop twice, 2nd time to commit everything.
//
//
// Constants.
//
static WCHAR const wcsSizeVar[] = L"CACHESIZE_"; unsigned ccSizeVar = sizeof(wcsSizeVar)/sizeof(WCHAR) - 1; static WCHAR const wcsTypeVar[] = L"CACHETYPE_"; unsigned ccTypeVar = sizeof(wcsTypeVar)/sizeof(WCHAR) - 1;
if ( 0 == _wcsnicmp( pwcsName, wcsSizeVar, ccSizeVar ) ) { CFullPropSpec ps;
//
// Parse the GUID.
//
unsigned cc = wcslen( pwcsName ); GUID guid;
if ( cc <= ccSizeVar || !ParseGuid( pwcsName + ccSizeVar, guid ) ) { ciGibDebugOut(( DEB_WARN, "Improperly formatted CACHESIZE entry %ws\n", pwcsName )); iter.Next(); continue; }
ps.SetPropSet( guid );
//
// PROPID or string?
//
static WCHAR const wcsName[] = L"_NAME_"; unsigned ccName = sizeof(wcsName)/sizeof(WCHAR) - 1; static WCHAR const wcsPropid[] = L"_PROPID_"; unsigned ccPropid = sizeof(wcsPropid)/sizeof(WCHAR) - 1;
if ( 0 == _wcsnicmp( pwcsName + ccSizeVar + ccStringizedGuid, wcsPropid, ccPropid ) ) { CQueryScanner scan( pwcsName + ccSizeVar + ccStringizedGuid + ccPropid, FALSE );
PROPID propid; BOOL fEnd;
if ( !scan.GetNumber( propid, fEnd ) ) { ciGibDebugOut(( DEB_WARN, "Improperly formatted CACHESIZE entry %ws\n", pwcsName )); iter.Next(); continue; }
ps.SetProperty( propid ); } else if ( 0 == _wcsnicmp( pwcsName + ccSizeVar + ccStringizedGuid, wcsName, ccName ) ) { ps.SetProperty( pwcsName + ccSizeVar + ccStringizedGuid + ccName ); } else { ciGibDebugOut(( DEB_WARN, "Improperly formatted CACHESIZE entry %ws\n", pwcsName )); iter.Next(); continue; }
//
// Get value.
//
PROPVARIANT * ppvSize = pVar->GetValue(); ULONG cb;
if ( ppvSize->vt == VT_LPWSTR ) { CQueryScanner scan( ppvSize->pwszVal, FALSE );
BOOL fEnd;
if ( !scan.GetNumber( cb, fEnd ) ) { ciGibDebugOut(( DEB_WARN, "Improper CACHESIZE size: \"%ws\".\n", ppvSize->pwszVal )); iter.Next(); continue; } } else { ciGibDebugOut(( DEB_IWARN, "Improper CACHESIZE size (type = %d).\n", ppvSize->vt )); iter.Next(); continue; }
if ( 0 == cb ) { //
// Delete property from cache (if it was even there).
//
//
// If IDA were the future...
// Need to allow primary or secondary store to be chosen!
// Also allow the ability to set true/false for prop meta info
// modifiability.
//
SCODE sc = SetupCacheEx( ps.CastToStruct(), 0, 0, ulToken, TRUE, PRIMARY_STORE, wcsCatalog.GetPointer(), wcsCatalog.GetPointer(), wcsMachine.GetPointer() );
if ( FAILED(sc) ) { ciGibDebugOut(( DEB_ERROR, "Error 0x%x modifying cache\n", sc )); THROW( CException( sc ) ); }
fSawOne = TRUE; iter.Next(); continue; }
//
// At this point, we have a non-zero size. The property will
// be added to the cache.
//
//
// Fetch data type
//
XArray<WCHAR> xVar(cc+1);
RtlCopyMemory( xVar.GetPointer(), pwcsName, (cc+1) * sizeof(WCHAR) ); RtlCopyMemory( xVar.GetPointer(), wcsTypeVar, ccTypeVar * sizeof(WCHAR) );
CVariable * pVarType = VarSet.Find( xVar.GetPointer() );
if ( 0 == pVarType ) { ciGibDebugOut(( DEB_WARN, "Missing CACHETYPE value.\n" )); iter.Next(); continue; }
PROPVARIANT * ppvType = pVarType->GetValue(); ULONG type;
if ( ppvType->vt == VT_LPWSTR ) { CQueryScanner scan( ppvType->pwszVal, FALSE );
BOOL fEnd;
if ( !scan.GetNumber( type, fEnd ) ) { ciGibDebugOut(( DEB_WARN, "Improper CACHETYPE type: \"%ws\".\n", ppvType->pwszVal )); iter.Next(); continue; } } else { ciGibDebugOut(( DEB_WARN, "Improper CACHETYPE size (type = %d).\n", ppvType->vt )); iter.Next(); continue; }
ciGibDebugOut(( DEB_WARN, "Add/change %ws\n", pwcsName ));
//
// If IDA were the future...
// Need to allow primary or secondary store to be chosen!
// Also allow the ability to set true/false for prop meta info
// modifiability.
//
SCODE sc = SetupCacheEx( ps.CastToStruct(), type, cb, ulToken, TRUE, SECONDARY_STORE, wcsCatalog.GetPointer(), wcsCatalog.GetPointer(), wcsMachine.GetPointer() );
if ( FAILED(sc) ) { ciGibDebugOut(( DEB_ERROR, "Error 0x%x modifying cache\n", sc )); THROW( CException( sc ) ); }
fSawOne = TRUE; }
iter.Next(); }
sc = EndCacheTransaction( ulToken, fSawOne, wcsCatalog.GetPointer(), wcsCatalog.GetPointer(), wcsMachine.GetPointer() );
if ( FAILED(sc) ) { ciGibDebugOut(( DEB_ERROR, "Error 0x%x completing cache transaction.\n", sc )); THROW( CException( sc ) ); } break; }
case CIDAFile::CiState: { //
// Populate the variable set.
//
CStorageVariant var;
var.SetUI4( TheWebQueryCache.Hits() ); VarSet.SetVariable( ISAPI_CI_ADMIN_CACHE_HITS, var, 0 );
var.SetUI4( TheWebQueryCache.Misses() ); VarSet.SetVariable( ISAPI_CI_ADMIN_CACHE_MISSES, var, 0 );
var.SetUI4( TheWebQueryCache.Running() ); VarSet.SetVariable( ISAPI_CI_ADMIN_CACHE_ACTIVE, var, 0 );
var.SetUI4( TheWebQueryCache.Cached() ); VarSet.SetVariable( ISAPI_CI_ADMIN_CACHE_COUNT, var, 0 );
var.SetUI4( TheWebPendingRequestQueue.Count() ); VarSet.SetVariable( ISAPI_CI_ADMIN_CACHE_PENDING, var, 0 );
var.SetUI4( TheWebQueryCache.Rejected() ); VarSet.SetVariable( ISAPI_CI_ADMIN_CACHE_REJECTED, var, 0 );
var.SetUI4( TheWebQueryCache.Total() ); VarSet.SetVariable( ISAPI_CI_ADMIN_CACHE_TOTAL, var, 0 );
var.SetUI4( TheWebQueryCache.QPM() ); VarSet.SetVariable( ISAPI_CI_ADMIN_CACHE_QPM, var, 0 );
//
// Fetch CI state.
//
CI_STATE sState; sState.cbStruct = sizeof(sState);
SCODE sc = CIState ( wcsCatalog.GetPointer(), wcsMachine.GetPointer(), &sState );
if ( FAILED(sc) ) { ciGibDebugOut(( DEB_ERROR, "Error 0x%x getting CI state.\n", sc )); THROW( CException( sc ) ); }
var.SetUI4( sState.cWordList ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_COUNT_WORDLISTS, var, 0 );
var.SetUI4( sState.cPersistentIndex ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_COUNT_PERSINDEX, var, 0 );
var.SetUI4( sState.cQueries ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_COUNT_QUERIES, var, 0 );
var.SetUI4( sState.cDocuments ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_COUNT_TOFILTER, var, 0 );
var.SetUI4( sState.cFreshTest ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_COUNT_FRESHTEST, var, 0 );
var.SetUI4( sState.dwMergeProgress ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_MERGE_PROGRESS, var, 0 );
var.SetUI4( sState.cPendingScans ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_COUNT_PENDINGSCANS, var, 0 );
var.SetUI4( sState.cFilteredDocuments ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_COUNT_FILTERED, var, 0 );
var.SetUI4( sState.cTotalDocuments ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_COUNT_TOTAL, var, 0 );
var.SetUI4( sState.cUniqueKeys ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_COUNT_UNIQUE, var, 0 );
var.SetUI4( sState.dwIndexSize ); VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_SIZE, var, 0 );
if ( sState.eState & CI_STATE_SHADOW_MERGE ) var.SetBOOL( VARIANT_TRUE ); else var.SetBOOL( VARIANT_FALSE );
VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_STATE_SHADOWMERGE, var, 0 );
if ( sState.eState & CI_STATE_MASTER_MERGE ) var.SetBOOL( VARIANT_TRUE ); else var.SetBOOL( VARIANT_FALSE );
VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_STATE_MASTERMERGE, var, 0 );
if ( sState.eState & CI_STATE_ANNEALING_MERGE ) var.SetBOOL( VARIANT_TRUE ); else var.SetBOOL( VARIANT_FALSE );
VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_STATE_ANNEALINGMERGE, var, 0 );
if ( sState.eState & CI_STATE_CONTENT_SCAN_REQUIRED ) var.SetBOOL( VARIANT_TRUE ); else var.SetBOOL( VARIANT_FALSE );
VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_STATE_SCANREQUIRED, var, 0 );
if ( sState.eState & CI_STATE_SCANNING ) var.SetBOOL( VARIANT_TRUE ); else var.SetBOOL( VARIANT_FALSE );
VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_STATE_SCANNING, var, 0 );
if ( sState.eState & CI_STATE_RECOVERING ) var.SetBOOL( VARIANT_TRUE ); else var.SetBOOL( VARIANT_FALSE );
VarSet.SetVariable( ISAPI_CI_ADMIN_INDEX_STATE_RECOVERING, var, 0 );
//
// Now that we've got the variables, we can parse the file.
//
SuccessHTX.ParseFile( wcsPhysicalName, VarSet, OutputFormat );
if ( SuccessHTX.DoesDetailSectionExist() ) { THROW( CIDQException(MSG_CI_IDA_TEMPLATE_DETAIL_SECTION, 0) ); }
break; }
case CIDAFile::ForceMerge: { SuccessHTX.ParseFile( wcsPhysicalName, VarSet, OutputFormat );
if ( SuccessHTX.DoesDetailSectionExist() ) { THROW( CIDQException(MSG_CI_IDA_TEMPLATE_DETAIL_SECTION, 0) ); }
SCODE sc = ForceMasterMerge( wcsCatalog.GetPointer(), // Drive
wcsCatalog.GetPointer(), // Catalog
wcsMachine.GetPointer(), // Machine
1 ); // Partition
if ( FAILED(sc) ) { ciGibDebugOut(( DEB_ERROR, "Error 0x%x calling ForceMerge for %ws\n", sc, wcsCatalog.GetPointer() )); THROW( CException( sc ) ); } break; } }
//
// Set CiQueryTime
//
ULONG cwcQueryTime = 40; SYSTEMTIME QueryTime; GetLocalTime( &QueryTime );
XArray<WCHAR> wcsQueryTime(cwcQueryTime+1); cwcQueryTime = OutputFormat.FormatTime( QueryTime, wcsQueryTime.GetPointer(), cwcQueryTime );
//
// SetCiQueryDate
//
ULONG cwcQueryDate = 40; XArray<WCHAR> wcsQueryDate(cwcQueryDate+1); cwcQueryDate = OutputFormat.FormatDate( QueryTime, wcsQueryDate.GetPointer(), cwcQueryDate );
VarSet.AcquireStringValue( ISAPI_CI_QUERY_TIME, wcsQueryTime.GetPointer(), 0 ); wcsQueryTime.Acquire();
VarSet.AcquireStringValue( ISAPI_CI_QUERY_DATE, wcsQueryDate.GetPointer(), 0 ); wcsQueryDate.Acquire();
//
// Set CiQueryTimeZone
//
TIME_ZONE_INFORMATION TimeZoneInformation; DWORD dwResult = GetTimeZoneInformation( &TimeZoneInformation ); LPWSTR pwszTimeZoneName = 0;
if ( TIME_ZONE_ID_DAYLIGHT == dwResult ) { pwszTimeZoneName = TimeZoneInformation.DaylightName; } else if ( 0xFFFFFFFF == dwResult ) { # if CIDBG == 1
DWORD dwError = GetLastError(); ciGibDebugOut(( DEB_ERROR, "Error %d from GetTimeZoneInformation.\n", dwError )); THROW(CException( HRESULT_FROM_WIN32(dwError) )); # else
THROW( CException() ); # endif
} else { pwszTimeZoneName = TimeZoneInformation.StandardName; }
VarSet.CopyStringValue( ISAPI_CI_QUERY_TIMEZONE, pwszTimeZoneName, 0);
//
// Set CiCatalog, CiLocale and CiTemplate
//
VarSet.AcquireStringValue( ISAPI_CI_CATALOG, wcsCiCatalog.GetPointer(), 0 ); wcsCiCatalog.Acquire();
VarSet.AcquireStringValue( ISAPI_CI_LOCALE, wcsLocale.GetPointer(), 0 ); wcsLocale.Acquire();
VarSet.CopyStringValue( ISAPI_CI_TEMPLATE, SuccessHTX.GetVirtualName(), 0 );
//
// If we got here, then all changes succeeded and we build success page.
//
SuccessHTX.GetHeader( vsResults, VarSet, OutputFormat ); SuccessHTX.GetFooter( vsResults, VarSet, OutputFormat ); }
BOOL ParseGuid( WCHAR const * pwcsGuid, GUID & guid ) { unsigned cc = wcslen( pwcsGuid );
if ( cc < ccStringizedGuid || L'-' != pwcsGuid[8] || L'-' != pwcsGuid[13] || L'-' != pwcsGuid[18] || L'-' != pwcsGuid[23] ) { ciGibDebugOut(( DEB_WARN, "Improperly formatted guid %ws\n", pwcsGuid )); return FALSE; }
//
// Copy into local, editable, storage
//
WCHAR wcsGuid[ccStringizedGuid + 1];
RtlCopyMemory( wcsGuid, pwcsGuid, (ccStringizedGuid + 1) * sizeof(WCHAR) ); wcsGuid[ccStringizedGuid] = 0;
wcsGuid[8] = 0; WCHAR * pwcStart = &wcsGuid[0]; WCHAR * pwcEnd; guid.Data1 = wcstoul( pwcStart, &pwcEnd, 16 ); if ( (pwcEnd-pwcStart) != 8 ) // The 1st number MUST be 8 digits long
return FALSE;
wcsGuid[13] = 0; pwcStart = &wcsGuid[9]; guid.Data2 = (USHORT)wcstoul( pwcStart, &pwcEnd, 16 ); if ( (pwcEnd-pwcStart) != 4 ) // The 2nd number MUST be 4 digits long
return FALSE;
wcsGuid[18] = 0; pwcStart = &wcsGuid[14]; guid.Data3 = (USHORT)wcstoul( pwcStart, &pwcEnd, 16 ); if ( (pwcEnd-pwcStart) != 4 ) // The 3rd number MUST be 4 digits long
return FALSE;
WCHAR wc = wcsGuid[21]; wcsGuid[21] = 0; pwcStart = &wcsGuid[19]; guid.Data4[0] = (unsigned char)wcstoul( pwcStart, &pwcEnd, 16 ); if ( (pwcEnd-pwcStart) != 2 ) // The 4th number MUST be 4 digits long
return FALSE; wcsGuid[21] = wc;
wcsGuid[23] = 0; pwcStart = &wcsGuid[21]; guid.Data4[1] = (unsigned char)wcstoul( pwcStart, &pwcEnd, 16 ); if ( (pwcEnd-pwcStart) != 2 ) // The 4th number MUST be 4 digits long
return FALSE;
for ( unsigned i = 0; i < 6; i++ ) { wc = wcsGuid[26+i*2]; wcsGuid[26+i*2] = 0; pwcStart = &wcsGuid[24+i*2]; guid.Data4[2+i] = (unsigned char)wcstoul( pwcStart, &pwcEnd, 16 ); if ( pwcStart == pwcEnd ) return FALSE;
wcsGuid[26+i*2] = wc; }
return TRUE; }
//+---------------------------------------------------------------------------
//
// Function: CheckAdminSecurity, public
//
// Synopsis: Checks to see if the client has administrative access.
//
// Arguments: [pwszMachine] - machine name
//
// Returns: Nothing, throws if access is denied.
//
// Notes: The ACL on the HKEY_CURRENT_MACHINE\system\CurrentControlSet\ // Control\ContentIndex registry key is used to determine if
// access is permitted.
//
// The access check is only done when the administrative operation
// is local. Otherwise, it will be checked in the course of doing
// the administrative operation.
//
// History: 26 Jun 96 AlanW Created.
//
//----------------------------------------------------------------------------
void CheckAdminSecurity( WCHAR const * pwszMachine ) { HKEY hNewKey = (HKEY) INVALID_HANDLE_VALUE;
if ( 0 != wcscmp( pwszMachine, CATURL_LOCAL_MACHINE ) ) return;
LONG dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, wcsRegAdminSubKey, 0, KEY_WRITE, &hNewKey );
if ( ERROR_SUCCESS == dwError ) { RegCloseKey( hNewKey ); } else if ( ERROR_ACCESS_DENIED == dwError ) { THROW(CException( STATUS_ACCESS_DENIED ) ); } else { ciGibDebugOut(( DEB_ERROR, "Can not open reg key %ws, error %d\n", wcsRegAdminSubKey, dwError )); THROW(CException( HRESULT_FROM_WIN32( dwError ) ) ); } }
|