1202 lines
37 KiB
C++
1202 lines
37 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1996-2000.
|
||
|
//
|
||
|
// File: idq.cxx
|
||
|
//
|
||
|
// Contents: Parser for an IDQ file
|
||
|
//
|
||
|
// History: 96/Jan/3 DwightKr Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include <pch.cxx>
|
||
|
#pragma hdrstop
|
||
|
|
||
|
//
|
||
|
// These hash values MUST be unique. They have been calculated to be
|
||
|
// unique via the ISAPI_IDQHash function below.
|
||
|
//
|
||
|
// If the spelling of a IDQ variable name is changed, or a new variable
|
||
|
// is added to the list, this table must be re-generated using the
|
||
|
// code supplied below.
|
||
|
//
|
||
|
static const ULONG ISAPI_CIBOOLVECTORPREFIX_HASH = 0x1174d5c;
|
||
|
static const ULONG ISAPI_CIBOOLVECTORSEPARATOR_HASH = 0x8ba6b1d;
|
||
|
static const ULONG ISAPI_CIBOOLVECTORSUFFIX_HASH = 0x1174df4;
|
||
|
static const ULONG ISAPI_CICATALOG_HASH = 0x89c6;
|
||
|
static const ULONG ISAPI_CICOLUMNS_HASH = 0x8bb4;
|
||
|
static const ULONG ISAPI_CICURRENCYVECTORPREFIX_HASH = 0x119add60;
|
||
|
static const ULONG ISAPI_CICURRENCYVECTORSEPARATOR_HASH = 0x8cd6eb21;
|
||
|
static const ULONG ISAPI_CICURRENCYVECTORSUFFIX_HASH = 0x119addf8;
|
||
|
static const ULONG ISAPI_CICURRENTPAGENUMBER_HASH = 0x233792f;
|
||
|
static const ULONG ISAPI_CICURRENTRECORDNUMBER_HASH = 0x8ce0671;
|
||
|
static const ULONG ISAPI_CIDATEVECTORPREFIX_HASH = 0x114fd5c;
|
||
|
static const ULONG ISAPI_CIDATEVECTORSEPARATOR_HASH = 0x8a7eb1d;
|
||
|
static const ULONG ISAPI_CIDATEVECTORSUFFIX_HASH = 0x114fdf4;
|
||
|
static const ULONG ISAPI_CIFORCEUSECI_HASH = 0x46337;
|
||
|
static const ULONG ISAPI_CIDEFERTRIMMING_HASH = 0x8a26e6f8;
|
||
|
static const ULONG ISAPI_CIDIALECT_HASH = 0x8a07;
|
||
|
static const ULONG ISAPI_CIFLAGS_HASH = 0x228c;
|
||
|
static const ULONG ISAPI_CILOCALE_HASH = 0x4631;
|
||
|
static const ULONG ISAPI_CIMATCHEDRECORDCOUNT_HASH = 0x4639280;
|
||
|
static const ULONG ISAPI_CIMAXRECORDSINRESULTSET_HASH = 0x2349b581;
|
||
|
static const ULONG ISAPI_CIMAXRECORDSPERPAGE_HASH = 0x2349baa;
|
||
|
static const ULONG ISAPI_CIFIRSTROWSINRESULTSET_HASH = 0x118dc580;
|
||
|
static const ULONG ISAPI_CINUMBERVECTORPREFIX_HASH = 0x476ad5e;
|
||
|
static const ULONG ISAPI_CINUMBERVECTORSEPARATOR_HASH = 0x23b56b1f;
|
||
|
static const ULONG ISAPI_CINUMBERVECTORSUFFIX_HASH = 0x476adf6;
|
||
|
static const ULONG ISAPI_CIRESTRICTION_HASH = 0x8ed8d;
|
||
|
static const ULONG ISAPI_CISCOPE_HASH = 0x2350;
|
||
|
static const ULONG ISAPI_CISORT_HASH = 0x11c2;
|
||
|
static const ULONG ISAPI_CISTRINGVECTORPREFIX_HASH = 0x4845d5e;
|
||
|
static const ULONG ISAPI_CISTRINGVECTORSEPARATOR_HASH = 0x2422eb1f;
|
||
|
static const ULONG ISAPI_CISTRINGVECTORSUFFIX_HASH = 0x4845df6;
|
||
|
static const ULONG ISAPI_CITEMPLATE_HASH = 0x11d3b;
|
||
|
static const ULONG ISAPI_CICANONICALOUTPUT_HASH = 0x8a0c9f;
|
||
|
static const ULONG ISAPI_CIDONTTIMEOUT_HASH = 0x8c55f;
|
||
|
|
||
|
#if 0
|
||
|
|
||
|
//
|
||
|
// Use the following routine to verify the above hash values are perfect.
|
||
|
//
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: main - program entry point; used to verify perfect hash
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
int __cdecl main( int argc, char ** argv )
|
||
|
{
|
||
|
ULONG aHash[100];
|
||
|
Win4Assert( 100 > cISAPI_CiParams );
|
||
|
|
||
|
for (unsigned i=0; i<cISAPI_CiParams; i++)
|
||
|
{
|
||
|
aHash[i] = ISAPI_IDQHash( aISAPI_CiParams[i] );
|
||
|
}
|
||
|
|
||
|
|
||
|
for (i=0; i<cISAPI_CiParams-1; i++)
|
||
|
{
|
||
|
for (unsigned j=i+1; j<cISAPI_CiParams; j++)
|
||
|
{
|
||
|
if ( aHash[i] == aHash[j] )
|
||
|
{
|
||
|
printf( "Hash collision between %ls(0x%x) and %ls(0x%x)\n",
|
||
|
aISAPI_CiParams[i],
|
||
|
aHash[i],
|
||
|
aISAPI_CiParams[j],
|
||
|
aHash[j] );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
printf ("Hash table: Copy this as necessary into idq\\idq.cxx\n");
|
||
|
for (i=0; i<cISAPI_CiParams; i++)
|
||
|
{
|
||
|
printf("static const ULONG ISAPI_%ws_HASH\t= 0x%x;\n", aISAPI_CiParams[i], aHash[i] );
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif // 0
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::CIDQFile - public constructor
|
||
|
//
|
||
|
// Synopsis: Builds a CIDQFile object, initializes values
|
||
|
//
|
||
|
// Arguments: [wcsFileName] -- full path to IDQ file
|
||
|
// [codePage] -- code page to translate IDQ file
|
||
|
//
|
||
|
// History: 96/Jan/03 DwightKr Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
CIDQFile::CIDQFile( WCHAR const * wcsFileName,
|
||
|
UINT codePage,
|
||
|
CSecurityIdentity const & securityIdentity )
|
||
|
: _wcsRestriction(0),
|
||
|
_wcsDialect(0),
|
||
|
_wcsScope(0),
|
||
|
_wcsSort(0),
|
||
|
_wcsColumns(0),
|
||
|
_wcsLocale(0),
|
||
|
_wcsHTXFileName(0),
|
||
|
_wcsMaxRecordsInResultSet(0),
|
||
|
_wcsMaxRecordsPerPage(0),
|
||
|
_wcsFirstRowsInResultSet(0),
|
||
|
_wcsCatalog(0),
|
||
|
_wcsForceUseCi(0),
|
||
|
_wcsDeferTrimming(0),
|
||
|
_wcsCanonicalOutput(0),
|
||
|
_wcsDontTimeout(0),
|
||
|
_wcsCiFlags(0),
|
||
|
_wcsBoolVectorPrefix(0),
|
||
|
_wcsBoolVectorSeparator(0),
|
||
|
_wcsBoolVectorSuffix(0),
|
||
|
_wcsCurrencyVectorPrefix(0),
|
||
|
_wcsCurrencyVectorSeparator(0),
|
||
|
_wcsCurrencyVectorSuffix(0),
|
||
|
_wcsDateVectorPrefix(0),
|
||
|
_wcsDateVectorSeparator(0),
|
||
|
_wcsDateVectorSuffix(0),
|
||
|
_wcsNumberVectorPrefix(0),
|
||
|
_wcsNumberVectorSeparator(0),
|
||
|
_wcsNumberVectorSuffix(0),
|
||
|
_wcsStringVectorPrefix(0),
|
||
|
_wcsStringVectorSeparator(0),
|
||
|
_wcsStringVectorSuffix(0),
|
||
|
_cReplaceableParameters(0),
|
||
|
_refCount(0),
|
||
|
_codePage(codePage),
|
||
|
_securityIdentity( securityIdentity )
|
||
|
{
|
||
|
wcscpy( _wcsIDQFileName, wcsFileName );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::~CIDQFile - public destructor
|
||
|
//
|
||
|
// History: 96/Jan/03 DwightKr Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
CIDQFile::~CIDQFile()
|
||
|
{
|
||
|
Win4Assert( _refCount == 0 );
|
||
|
|
||
|
delete _wcsRestriction;
|
||
|
delete _wcsDialect;
|
||
|
delete _wcsScope;
|
||
|
delete _wcsSort;
|
||
|
delete _wcsColumns;
|
||
|
delete _wcsLocale;
|
||
|
delete _wcsHTXFileName;
|
||
|
delete _wcsMaxRecordsInResultSet;
|
||
|
delete _wcsMaxRecordsPerPage;
|
||
|
delete _wcsFirstRowsInResultSet;
|
||
|
delete _wcsCatalog;
|
||
|
delete _wcsCiFlags;
|
||
|
delete _wcsForceUseCi;
|
||
|
delete _wcsDeferTrimming;
|
||
|
delete _wcsCanonicalOutput;
|
||
|
delete _wcsDontTimeout;
|
||
|
delete _wcsBoolVectorPrefix;
|
||
|
delete _wcsBoolVectorSeparator;
|
||
|
delete _wcsBoolVectorSuffix;
|
||
|
delete _wcsCurrencyVectorPrefix;
|
||
|
delete _wcsCurrencyVectorSeparator;
|
||
|
delete _wcsCurrencyVectorSuffix;
|
||
|
delete _wcsDateVectorPrefix;
|
||
|
delete _wcsDateVectorSeparator;
|
||
|
delete _wcsDateVectorSuffix;
|
||
|
delete _wcsNumberVectorPrefix;
|
||
|
delete _wcsNumberVectorSeparator;
|
||
|
delete _wcsNumberVectorSuffix;
|
||
|
delete _wcsStringVectorPrefix;
|
||
|
delete _wcsStringVectorSeparator;
|
||
|
delete _wcsStringVectorSuffix;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::ParseFile, private
|
||
|
//
|
||
|
// Synopsis: Parses the given file and sets up the necessary variables
|
||
|
//
|
||
|
// History: 96/Jan/03 DwightKr Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CIDQFile::ParseFile()
|
||
|
{
|
||
|
_xList.Set(new CLocalGlobalPropertyList( _codePage ));
|
||
|
|
||
|
// We don't support impersonation for scripts.
|
||
|
// It involves getting the server ip address, vpath and then using
|
||
|
// that for impersonation
|
||
|
|
||
|
Win4Assert( !IsNetPath( _wcsIDQFileName ) );
|
||
|
|
||
|
//
|
||
|
// Now parse the query parameters
|
||
|
//
|
||
|
|
||
|
// Open the file in a TRY block, so we can make this an IDQ error
|
||
|
// if the IDQ file isn't found. Otherwise the error doesn't include
|
||
|
// the IDQ filename.
|
||
|
// For scoping reasons, the CFileMapView is new'ed, not on the stack.
|
||
|
|
||
|
XPtr<CFileMapView> xMapView;
|
||
|
|
||
|
TRY
|
||
|
{
|
||
|
xMapView.Set( new CFileMapView( _wcsIDQFileName ) );
|
||
|
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 idqFile( xMapView.GetReference(), _codePage );
|
||
|
|
||
|
//
|
||
|
// Save the last write time of this file.
|
||
|
//
|
||
|
|
||
|
SCODE sc = GetLastWriteTime( _wcsIDQFileName, _ftIDQLastWriteTime );
|
||
|
|
||
|
if ( FAILED( sc ) )
|
||
|
THROW( CException( sc ) );
|
||
|
|
||
|
//
|
||
|
// Process a line at a time, look for either the [Names] or the [Query]
|
||
|
// section and process lines within those sections.
|
||
|
//
|
||
|
|
||
|
BOOL fQuerySection = FALSE;
|
||
|
BOOL fNamesSection = FALSE;
|
||
|
int iLine = 0; // Start counting at line #1
|
||
|
|
||
|
for( ;; )
|
||
|
{
|
||
|
iLine++;
|
||
|
XGrowable<WCHAR> xLine;
|
||
|
|
||
|
ULONG cwcChar = idqFile.fgetsw( xLine );
|
||
|
|
||
|
if ( 0 == cwcChar )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
WCHAR *pwcLine = xLine.Get();
|
||
|
|
||
|
//
|
||
|
// Skip ahead until we find a [Query] section
|
||
|
//
|
||
|
if ( L'[' == *pwcLine )
|
||
|
{
|
||
|
if (_wcsnicmp(pwcLine+1, L"Query]", 6) == 0 )
|
||
|
{
|
||
|
fQuerySection = TRUE;
|
||
|
continue;
|
||
|
}
|
||
|
else if (_wcsnicmp(pwcLine+1, L"Names]", 6) == 0 )
|
||
|
{
|
||
|
fNamesSection = TRUE;
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fQuerySection = fNamesSection = FALSE;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
else if ( L'#' == *pwcLine )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
if ( fQuerySection )
|
||
|
{
|
||
|
CQueryScanner scanner( pwcLine, FALSE );
|
||
|
ParseOneLine( scanner, iLine );
|
||
|
}
|
||
|
else if (fNamesSection)
|
||
|
{
|
||
|
XPtr<CPropEntry> propentry;
|
||
|
|
||
|
CQueryScanner scanner( pwcLine, FALSE );
|
||
|
CPropertyList::ParseOneLine(scanner, iLine, propentry);
|
||
|
if (propentry.GetPointer())
|
||
|
{
|
||
|
_xList->AddEntry( propentry.GetPointer(), iLine );
|
||
|
propentry.Acquire();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Verify that the minimum set of parameters are specified.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// We must have all of the following:
|
||
|
//
|
||
|
// - a restriction
|
||
|
// - a scope
|
||
|
// - a template (HTX) file
|
||
|
// - output columns
|
||
|
//
|
||
|
|
||
|
if ( 0 == _wcsRestriction )
|
||
|
{
|
||
|
// Report an error
|
||
|
ciGibDebugOut(( DEB_IERROR, "Restriction not found in IDQ file\n" ));
|
||
|
THROW( CIDQException(MSG_CI_IDQ_MISSING_RESTRICTION, 0) );
|
||
|
}
|
||
|
else if ( 0 == _wcsScope )
|
||
|
{
|
||
|
// Report an error
|
||
|
ciGibDebugOut(( DEB_IERROR, "Scope not found in IDQ file\n" ));
|
||
|
THROW( CIDQException(MSG_CI_IDQ_MISSING_SCOPE, 0) );
|
||
|
}
|
||
|
else if ( 0 == _wcsHTXFileName && !IsCanonicalOutput() )
|
||
|
{
|
||
|
// Report an error
|
||
|
ciGibDebugOut(( DEB_IERROR, "HTX filename not found in IDQ file\n" ));
|
||
|
THROW( CIDQException(MSG_CI_IDQ_MISSING_TEMPLATEFILE, 0) );
|
||
|
}
|
||
|
else if ( 0 == _wcsColumns )
|
||
|
{
|
||
|
// Report an error
|
||
|
ciGibDebugOut(( DEB_IERROR, "Output columns not found in IDQ file\n" ));
|
||
|
THROW( CIDQException(MSG_CI_IDQ_MISSING_OUTPUTCOLUMNS, 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: CIDQFile::ParseOneLine, private
|
||
|
//
|
||
|
// Synopsis: Parses one line of the IDQ file
|
||
|
//
|
||
|
// Arguments: [scan] -- scanner initialized with the current line
|
||
|
// [iLine] -- current line number
|
||
|
//
|
||
|
// History: 96/Jan/03 DwightKr created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CIDQFile::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();
|
||
|
|
||
|
|
||
|
//
|
||
|
// Convert the string to upper-case and HASH it. Lookup the hashed value.
|
||
|
// Note that this code assumes the HASH IS PERFECT. Whenever a IDQ
|
||
|
// variable is renamed or added, this assumption may no-longer be true.
|
||
|
// Check it out with the above program.
|
||
|
//
|
||
|
// This code essentially replaces 25 wcsicmp functions; or an average
|
||
|
// of 12.5 wscicmp calls per line in the IDQ file.
|
||
|
//
|
||
|
Win4Assert( ISAPI_CICOLUMNS_HASH == ISAPI_IDQHash(ISAPI_CI_COLUMNS) );
|
||
|
Win4Assert( ISAPI_CIFLAGS_HASH == ISAPI_IDQHash(ISAPI_CI_FLAGS) );
|
||
|
Win4Assert( ISAPI_CIMAXRECORDSINRESULTSET_HASH == ISAPI_IDQHash(ISAPI_CI_MAX_RECORDS_IN_RESULTSET) );
|
||
|
Win4Assert( ISAPI_CIMAXRECORDSPERPAGE_HASH == ISAPI_IDQHash(ISAPI_CI_MAX_RECORDS_PER_PAGE) );
|
||
|
Win4Assert( ISAPI_CIFIRSTROWSINRESULTSET_HASH == ISAPI_IDQHash(ISAPI_CI_FIRST_ROWS_IN_RESULTSET) );
|
||
|
Win4Assert( ISAPI_CIRESTRICTION_HASH == ISAPI_IDQHash(ISAPI_CI_RESTRICTION) );
|
||
|
Win4Assert( ISAPI_CIDIALECT_HASH == ISAPI_IDQHash(ISAPI_CI_DIALECT) );
|
||
|
Win4Assert( ISAPI_CISCOPE_HASH == ISAPI_IDQHash(ISAPI_CI_SCOPE) );
|
||
|
Win4Assert( ISAPI_CISORT_HASH == ISAPI_IDQHash(ISAPI_CI_SORT) );
|
||
|
Win4Assert( ISAPI_CITEMPLATE_HASH == ISAPI_IDQHash(ISAPI_CI_TEMPLATE) );
|
||
|
Win4Assert( ISAPI_CICATALOG_HASH == ISAPI_IDQHash(ISAPI_CI_CATALOG) );
|
||
|
Win4Assert( ISAPI_CILOCALE_HASH == ISAPI_IDQHash(ISAPI_CI_LOCALE) );
|
||
|
Win4Assert( ISAPI_CIBOOLVECTORPREFIX_HASH == ISAPI_IDQHash(ISAPI_CI_BOOL_VECTOR_PREFIX) );
|
||
|
Win4Assert( ISAPI_CIBOOLVECTORSEPARATOR_HASH == ISAPI_IDQHash(ISAPI_CI_BOOL_VECTOR_SEPARATOR) );
|
||
|
Win4Assert( ISAPI_CIBOOLVECTORSUFFIX_HASH == ISAPI_IDQHash(ISAPI_CI_BOOL_VECTOR_SUFFIX) );
|
||
|
Win4Assert( ISAPI_CICURRENCYVECTORPREFIX_HASH == ISAPI_IDQHash(ISAPI_CI_CURRENCY_VECTOR_PREFIX) );
|
||
|
Win4Assert( ISAPI_CICURRENCYVECTORSEPARATOR_HASH == ISAPI_IDQHash(ISAPI_CI_CURRENCY_VECTOR_SEPARATOR) );
|
||
|
Win4Assert( ISAPI_CICURRENCYVECTORSUFFIX_HASH == ISAPI_IDQHash(ISAPI_CI_CURRENCY_VECTOR_SUFFIX) );
|
||
|
Win4Assert( ISAPI_CIDATEVECTORPREFIX_HASH == ISAPI_IDQHash(ISAPI_CI_DATE_VECTOR_PREFIX) );
|
||
|
Win4Assert( ISAPI_CIDATEVECTORSEPARATOR_HASH == ISAPI_IDQHash(ISAPI_CI_DATE_VECTOR_SEPARATOR) );
|
||
|
Win4Assert( ISAPI_CIDATEVECTORSUFFIX_HASH == ISAPI_IDQHash(ISAPI_CI_DATE_VECTOR_SUFFIX) );
|
||
|
Win4Assert( ISAPI_CINUMBERVECTORPREFIX_HASH == ISAPI_IDQHash(ISAPI_CI_NUMBER_VECTOR_PREFIX) );
|
||
|
Win4Assert( ISAPI_CINUMBERVECTORSEPARATOR_HASH == ISAPI_IDQHash(ISAPI_CI_NUMBER_VECTOR_SEPARATOR) );
|
||
|
Win4Assert( ISAPI_CINUMBERVECTORSUFFIX_HASH == ISAPI_IDQHash(ISAPI_CI_NUMBER_VECTOR_SUFFIX) );
|
||
|
Win4Assert( ISAPI_CISTRINGVECTORPREFIX_HASH == ISAPI_IDQHash(ISAPI_CI_STRING_VECTOR_PREFIX) );
|
||
|
Win4Assert( ISAPI_CISTRINGVECTORSEPARATOR_HASH == ISAPI_IDQHash(ISAPI_CI_STRING_VECTOR_SEPARATOR) );
|
||
|
Win4Assert( ISAPI_CISTRINGVECTORSUFFIX_HASH == ISAPI_IDQHash(ISAPI_CI_STRING_VECTOR_SUFFIX) );
|
||
|
Win4Assert( ISAPI_CIFORCEUSECI_HASH == ISAPI_IDQHash(ISAPI_CI_FORCE_USE_CI) );
|
||
|
Win4Assert( ISAPI_CIDEFERTRIMMING_HASH == ISAPI_IDQHash(ISAPI_CI_DEFER_NONINDEXED_TRIMMING ) );
|
||
|
Win4Assert( ISAPI_CICANONICALOUTPUT_HASH == ISAPI_IDQHash(ISAPI_CI_CANONICAL_OUTPUT ) );
|
||
|
Win4Assert( ISAPI_CIDONTTIMEOUT_HASH == ISAPI_IDQHash(ISAPI_CI_DONT_TIMEOUT ) );
|
||
|
|
||
|
_wcsupr( wcsAttribute.GetPointer() );
|
||
|
ULONG ulHash = ISAPI_IDQHash( wcsAttribute.GetPointer() );
|
||
|
|
||
|
switch ( ulHash )
|
||
|
{
|
||
|
case ISAPI_CICOLUMNS_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsColumns );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIFLAGS_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsCiFlags );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIMAXRECORDSINRESULTSET_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsMaxRecordsInResultSet );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIMAXRECORDSPERPAGE_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsMaxRecordsPerPage );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIFIRSTROWSINRESULTSET_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsFirstRowsInResultSet );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIRESTRICTION_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsRestriction );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIDIALECT_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsDialect );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CISCOPE_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsScope, FALSE );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CISORT_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsSort );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CITEMPLATE_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsHTXFileName );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CICATALOG_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsCatalog );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIBOOLVECTORPREFIX_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsBoolVectorPrefix );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIBOOLVECTORSEPARATOR_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsBoolVectorSeparator );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIBOOLVECTORSUFFIX_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsBoolVectorSuffix );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CICURRENCYVECTORPREFIX_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsCurrencyVectorPrefix );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CICURRENCYVECTORSEPARATOR_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsCurrencyVectorSeparator );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CICURRENCYVECTORSUFFIX_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsCurrencyVectorSuffix );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIDATEVECTORPREFIX_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsDateVectorPrefix );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIDATEVECTORSEPARATOR_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsDateVectorSeparator );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIDATEVECTORSUFFIX_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsDateVectorSuffix );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CINUMBERVECTORPREFIX_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsNumberVectorPrefix );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CINUMBERVECTORSEPARATOR_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsNumberVectorSeparator );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CINUMBERVECTORSUFFIX_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsNumberVectorSuffix );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CISTRINGVECTORPREFIX_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsStringVectorPrefix );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CISTRINGVECTORSEPARATOR_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsStringVectorSeparator );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CISTRINGVECTORSUFFIX_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsStringVectorSuffix );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIFORCEUSECI_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsForceUseCi );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIDEFERTRIMMING_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsDeferTrimming );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CILOCALE_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsLocale );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CICANONICALOUTPUT_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsCanonicalOutput );
|
||
|
break;
|
||
|
|
||
|
case ISAPI_CIDONTTIMEOUT_HASH:
|
||
|
GetStringValue( scan, iLine, &_wcsDontTimeout );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
|
||
|
|
||
|
//
|
||
|
// 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 .IDQ file versions with new parameters.
|
||
|
//
|
||
|
ciGibDebugOut(( DEB_ERROR,
|
||
|
"Invalid string in hash table for %ws; hash = 0x%x\n",
|
||
|
wcsAttribute.GetPointer(),
|
||
|
ulHash ));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::ParseColumns, public
|
||
|
//
|
||
|
// Synopsis: Parses the columns attribute
|
||
|
//
|
||
|
// Arguments: [wcsColumns] -- string to convert
|
||
|
// [variableSet] -- list of replaceable parameters
|
||
|
// [varColumns] -- Column variables returned here
|
||
|
//
|
||
|
// Returns: CDbColumns* - counted array of column IDs
|
||
|
//
|
||
|
// History: 96/Jan/03 DwightKr created
|
||
|
// 96/Feb/23 DwightKr Add check for duplicate value
|
||
|
// 96/Mar/12 DwightKr Made public
|
||
|
// 96/May/23 AlanW Detect duplicate column names
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CDbColumns * CIDQFile::ParseColumns( WCHAR const * wcsColumns,
|
||
|
CVariableSet & variableSet,
|
||
|
CDynArray<WCHAR> & awcsColumns )
|
||
|
{
|
||
|
return ::ParseStringColumns( wcsColumns,
|
||
|
_xList.GetPointer(),
|
||
|
GetUserDefaultLCID(),
|
||
|
&variableSet,
|
||
|
&awcsColumns );
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::ParseFlags, private
|
||
|
//
|
||
|
// Synopsis: Parses the flags attribute
|
||
|
//
|
||
|
// Arguments: [wcsCiFlags] -- flags
|
||
|
//
|
||
|
// History: 96/Jan/03 DwightKr created
|
||
|
// 96/Apr/12 DwightKr mad a replaceable parameter
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
ULONG CIDQFile::ParseFlags( WCHAR const * wcsCiFlags )
|
||
|
{
|
||
|
if ( 0 == wcsCiFlags )
|
||
|
{
|
||
|
return QUERY_DEEP;
|
||
|
}
|
||
|
|
||
|
ULONG ulFlags;
|
||
|
|
||
|
if ( _wcsicmp(wcsCiFlags, L"SHALLOW") == 0 )
|
||
|
{
|
||
|
ulFlags = QUERY_SHALLOW;
|
||
|
}
|
||
|
else if ( _wcsicmp(wcsCiFlags, L"DEEP") == 0 )
|
||
|
{
|
||
|
ulFlags = QUERY_DEEP;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
THROW( CIDQException(MSG_CI_IDQ_EXPECTING_SHALLOWDEEP, 0) );
|
||
|
}
|
||
|
|
||
|
return ulFlags;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::IsCanonicalOutput
|
||
|
//
|
||
|
// Synopsis: Tests if canonical output is enabled.
|
||
|
//
|
||
|
// Returns: TRUE if canonical output is needed; FALSE o/w
|
||
|
//
|
||
|
// History: 6-14-96 srikants Created
|
||
|
//
|
||
|
// Notes: Assumed here that it is not a replaceable parameter.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL CIDQFile::IsCanonicalOutput() const
|
||
|
{
|
||
|
if ( 0 == _wcsCanonicalOutput )
|
||
|
return FALSE;
|
||
|
|
||
|
return _wcsicmp(_wcsCanonicalOutput, L"TRUE") == 0;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::IsDontTimeout
|
||
|
//
|
||
|
// Synopsis: Specifies if the don't timeout parameter is true
|
||
|
//
|
||
|
// History: 9-13-96 srikants Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL CIDQFile::IsDontTimeout() const
|
||
|
{
|
||
|
if ( 0 == _wcsDontTimeout )
|
||
|
return FALSE;
|
||
|
|
||
|
return _wcsicmp(_wcsDontTimeout, L"TRUE") == 0;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::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
|
||
|
// [fParseQuotes] -- if TRUE, remove first and trailing quotes
|
||
|
//
|
||
|
// History: 96/Jan/03 DwightKr created
|
||
|
// 96/Feb/23 DwightKr Add check for duplicate value
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CIDQFile::GetStringValue( CQueryScanner & scan,
|
||
|
unsigned iLine,
|
||
|
WCHAR ** pwcsStringValue,
|
||
|
BOOL fParseQuotes )
|
||
|
{
|
||
|
if ( 0 != *pwcsStringValue )
|
||
|
{
|
||
|
ciGibDebugOut(( DEB_IWARN,
|
||
|
"Duplicate CiXX=value in IDQ file on line #%d\n",
|
||
|
iLine ));
|
||
|
THROW( CIDQException(MSG_CI_IDQ_DUPLICATE_ENTRY, iLine) );
|
||
|
}
|
||
|
|
||
|
*pwcsStringValue = scan.AcqLine( fParseQuotes );
|
||
|
|
||
|
if ( IsAReplaceableParameter( *pwcsStringValue ) != eIsSimpleString )
|
||
|
{
|
||
|
_cReplaceableParameters++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::IsCachedDataValid - public
|
||
|
//
|
||
|
// Synopsis: Determines if the IDQ file is still vaid, or has it
|
||
|
// changed since it was last read.
|
||
|
//
|
||
|
// History: 96/Jan/03 DwightKr created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL CIDQFile::IsCachedDataValid()
|
||
|
{
|
||
|
FILETIME ft;
|
||
|
SCODE sc = GetLastWriteTime( _wcsIDQFileName, ft );
|
||
|
|
||
|
// this usually fails because the file no longer exists
|
||
|
|
||
|
if ( FAILED( sc ) )
|
||
|
return FALSE;
|
||
|
|
||
|
return ( (_ftIDQLastWriteTime.dwLowDateTime == ft.dwLowDateTime) &&
|
||
|
(_ftIDQLastWriteTime.dwHighDateTime == ft.dwHighDateTime) );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: GetLastWriteTime
|
||
|
//
|
||
|
// Purpose: Gets the last change time of the file specified
|
||
|
//
|
||
|
// Arguments: [wcsFileName] - name of file to get last write time of
|
||
|
// [filetime] - where the filetime is returned
|
||
|
//
|
||
|
// Returns: SCODE result
|
||
|
//
|
||
|
// History: 96/Jan/23 DwightKr Created
|
||
|
// 96/Mar/13 DwightKr Changed to use GetFileAttributesEx()
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
SCODE GetLastWriteTime(
|
||
|
WCHAR const * wcsFileName,
|
||
|
FILETIME & filetime )
|
||
|
{
|
||
|
Win4Assert( 0 != wcsFileName );
|
||
|
|
||
|
// CImpersonateRemoteAccess imprsnat;
|
||
|
// imprsnat.ImpersonateIf( wcsFileName );
|
||
|
|
||
|
WIN32_FIND_DATA ffData;
|
||
|
|
||
|
if ( !GetFileAttributesEx( wcsFileName, GetFileExInfoStandard, &ffData ) )
|
||
|
{
|
||
|
ULONG error = GetLastError();
|
||
|
|
||
|
ciGibDebugOut(( DEB_IERROR,
|
||
|
"Unable to GetFileAttributesEx(%ws) GetLastError=0x%x\n",
|
||
|
wcsFileName,
|
||
|
error ));
|
||
|
return HRESULT_FROM_WIN32( error );
|
||
|
}
|
||
|
|
||
|
filetime = ffData.ftLastWriteTime;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::ParseForceUseCI - public
|
||
|
//
|
||
|
// Synopsis: Gets the TRUE/FALSE value for CiForceUseCI
|
||
|
//
|
||
|
// Arguments: [wcsForceUseCi] -- string to parse
|
||
|
//
|
||
|
// History: 96/Mar/03 DwightKr created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL CIDQFile::ParseForceUseCI( WCHAR const * wcsForceUseCi )
|
||
|
{
|
||
|
if ( 0 == wcsForceUseCi )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL fForceUseCi;
|
||
|
|
||
|
if ( _wcsicmp( wcsForceUseCi, L"FALSE" ) == 0 )
|
||
|
{
|
||
|
fForceUseCi = FALSE;
|
||
|
}
|
||
|
else if ( _wcsicmp( wcsForceUseCi, L"TRUE" ) == 0 )
|
||
|
{
|
||
|
fForceUseCi = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
THROW( CIDQException(MSG_CI_IDQ_EXPECTING_TRUEFALSE, 0) );
|
||
|
}
|
||
|
|
||
|
return fForceUseCi;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::ParseDeferTrimming - public
|
||
|
//
|
||
|
// Synopsis: Gets the TRUE/FALSE value for CiDeferNonIndexedTrimming
|
||
|
//
|
||
|
// Arguments: [wcsDeferTrimming] -- string to parse
|
||
|
//
|
||
|
// History: 96/Mar/03 DwightKr created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL CIDQFile::ParseDeferTrimming( WCHAR const * wcsDeferTrimming )
|
||
|
{
|
||
|
if ( 0 == wcsDeferTrimming )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL fDeferTrimming;
|
||
|
|
||
|
if ( _wcsicmp( wcsDeferTrimming, L"FALSE" ) == 0 )
|
||
|
{
|
||
|
fDeferTrimming = FALSE;
|
||
|
}
|
||
|
else if ( _wcsicmp( wcsDeferTrimming, L"TRUE" ) == 0 )
|
||
|
{
|
||
|
fDeferTrimming = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
THROW( CIDQException(MSG_CI_IDQ_EXPECTING_TRUEFALSE, 0) );
|
||
|
}
|
||
|
|
||
|
return fDeferTrimming;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFile::GetVectorFormatting, public
|
||
|
//
|
||
|
// Synopsis: Sets up the vector formatting for output
|
||
|
//
|
||
|
// Arguments: [outputFormat] -- the output format object to setup
|
||
|
//
|
||
|
// History: 96/Feb/26 DwightKr created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CIDQFile::GetVectorFormatting( COutputFormat & outputFormat )
|
||
|
{
|
||
|
outputFormat.SetBoolVectorFormat( _wcsBoolVectorPrefix,
|
||
|
_wcsBoolVectorSeparator,
|
||
|
_wcsBoolVectorSuffix );
|
||
|
|
||
|
outputFormat.SetCurrencyVectorFormat( _wcsCurrencyVectorPrefix,
|
||
|
_wcsCurrencyVectorSeparator,
|
||
|
_wcsCurrencyVectorSuffix );
|
||
|
|
||
|
outputFormat.SetDateVectorFormat( _wcsDateVectorPrefix,
|
||
|
_wcsDateVectorSeparator,
|
||
|
_wcsDateVectorSuffix );
|
||
|
|
||
|
outputFormat.SetNumberVectorFormat( _wcsNumberVectorPrefix,
|
||
|
_wcsNumberVectorSeparator,
|
||
|
_wcsNumberVectorSuffix );
|
||
|
|
||
|
outputFormat.SetStringVectorFormat( _wcsStringVectorPrefix,
|
||
|
_wcsStringVectorSeparator,
|
||
|
_wcsStringVectorSuffix );
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFileList::Find - public
|
||
|
//
|
||
|
// Synopsis: Finds a matching parsed IDQ file in list, or builds a new
|
||
|
// one if a match can not be found.
|
||
|
//
|
||
|
// Arguments: [wcsFileName] -- full path to IDQ file
|
||
|
// [codePage] -- code page of parsed IDQ file
|
||
|
//
|
||
|
// History: 96/Mar/27 DwightKr Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
CIDQFile * CIDQFileList::Find( WCHAR const * wcsFileName,
|
||
|
UINT codePage,
|
||
|
CSecurityIdentity const & securityIdentity )
|
||
|
{
|
||
|
//
|
||
|
// Refcount everything in the list so that we can examine the list
|
||
|
// outside of the lock.
|
||
|
//
|
||
|
|
||
|
ULONG cItems;
|
||
|
XArray<CIDQFile *> aIDQFile;
|
||
|
|
||
|
// ==========================================
|
||
|
{
|
||
|
CLock lock( _mutex );
|
||
|
|
||
|
cItems = _aIDQFile.Count(); // Save count of items to examine
|
||
|
aIDQFile.Init( cItems );
|
||
|
|
||
|
for (unsigned i=0; i<cItems; i++)
|
||
|
{
|
||
|
aIDQFile[i] = _aIDQFile[i];
|
||
|
aIDQFile[i]->LokAddRef();
|
||
|
}
|
||
|
}
|
||
|
// ==========================================
|
||
|
|
||
|
// Can't throw while the .idq files are addref'ed -- remember the
|
||
|
// error and throw it after the .idq files are released.
|
||
|
// IsCachedDataValid() throws!
|
||
|
|
||
|
SCODE sc = S_OK;
|
||
|
CIDQFile * pIDQFile = 0;
|
||
|
|
||
|
TRY
|
||
|
{
|
||
|
//
|
||
|
// Now walk though the list looking for a match; outside of the lock.
|
||
|
//
|
||
|
|
||
|
for (unsigned i=0; i<cItems; i++)
|
||
|
{
|
||
|
if ( (_wcsicmp(aIDQFile[i]->GetIDQFileName(), wcsFileName) == 0) &&
|
||
|
(aIDQFile[i]->GetCodePage() == codePage) &&
|
||
|
(aIDQFile[i]->IsCachedDataValid() )
|
||
|
)
|
||
|
{
|
||
|
pIDQFile = aIDQFile[i];
|
||
|
|
||
|
ciGibDebugOut(( DEB_ITRACE,
|
||
|
"A cached version of IDQ file %ws was found\n",
|
||
|
wcsFileName ));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
CATCH( CException, e )
|
||
|
{
|
||
|
sc = e.GetErrorCode();
|
||
|
}
|
||
|
END_CATCH
|
||
|
|
||
|
//
|
||
|
// If pIDQFile is non-0, we've found a match. Decrement the ref-count
|
||
|
// for all items which did not match.
|
||
|
//
|
||
|
|
||
|
for (unsigned i=0; i<cItems; i++)
|
||
|
{
|
||
|
if ( pIDQFile != aIDQFile[i] )
|
||
|
{
|
||
|
aIDQFile[i]->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( S_OK != sc )
|
||
|
{
|
||
|
Win4Assert( 0 == pIDQFile );
|
||
|
THROW( CException( sc ) );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We may have matched, but still not have access to this file. First, make
|
||
|
// a quick check for an exact match on security token, and then try harder
|
||
|
// by opening the file.
|
||
|
//
|
||
|
|
||
|
if ( 0 != pIDQFile )
|
||
|
{
|
||
|
if ( !pIDQFile->CheckSecurity( securityIdentity ) )
|
||
|
{
|
||
|
HANDLE h = CreateFile( wcsFileName,
|
||
|
GENERIC_READ,
|
||
|
FILE_SHARE_READ,
|
||
|
0,
|
||
|
OPEN_EXISTING,
|
||
|
0,
|
||
|
0 );
|
||
|
|
||
|
//
|
||
|
// Don't try to determine here if security caused the problem.
|
||
|
// Just let the standard exception handling below in file parsing
|
||
|
// deal with the error.
|
||
|
//
|
||
|
|
||
|
if ( INVALID_HANDLE_VALUE == h )
|
||
|
{
|
||
|
pIDQFile->Release();
|
||
|
pIDQFile = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CloseHandle( h );
|
||
|
|
||
|
//
|
||
|
// Update the security token of the cached Idq file,
|
||
|
// to optimize away the CreateFile check in two cases:
|
||
|
// 1. When the file is first parsed with admin
|
||
|
// privileges, and all subsequent queries are with
|
||
|
// anonymous privileges.
|
||
|
// 2. When the security token changes over time
|
||
|
//
|
||
|
pIDQFile->SetSecurityToken( securityIdentity );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we didn't find a match, then open and parse a new IDQ file, and
|
||
|
// add it to the list of parsed IDQ files
|
||
|
//
|
||
|
|
||
|
if ( 0 == pIDQFile )
|
||
|
{
|
||
|
ciGibDebugOut(( DEB_ITRACE, "Adding IDQ file %ws to cache\n", wcsFileName ));
|
||
|
|
||
|
pIDQFile = new CIDQFile(wcsFileName, codePage, securityIdentity);
|
||
|
XPtr<CIDQFile> xIDQFile( pIDQFile );
|
||
|
|
||
|
pIDQFile->ParseFile();
|
||
|
|
||
|
{
|
||
|
// ==========================================
|
||
|
CLock lock( _mutex );
|
||
|
_aIDQFile.Add( pIDQFile, _aIDQFile.Count() );
|
||
|
pIDQFile->LokAddRef();
|
||
|
// ==========================================
|
||
|
}
|
||
|
|
||
|
xIDQFile.Acquire();
|
||
|
}
|
||
|
|
||
|
return pIDQFile;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFileList::~CIDQFileList - public destructor
|
||
|
//
|
||
|
// History: 96/Mar/27 DwightKr Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
CIDQFileList::~CIDQFileList()
|
||
|
{
|
||
|
for (unsigned i=0; i<_aIDQFile.Count(); i++)
|
||
|
{
|
||
|
ciGibDebugOut(( DEB_ITRACE,
|
||
|
"Deleting IDQ cache entry %ws\n",
|
||
|
_aIDQFile[i]->GetIDQFileName() ));
|
||
|
|
||
|
delete _aIDQFile[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFileList::Release - public
|
||
|
//
|
||
|
// Synopsis: Releases the IDQ file by decrementing its refcount.
|
||
|
//
|
||
|
// Arguments: [idqFile] -- pointer to the IDQ file object
|
||
|
//
|
||
|
// History: 96/Mar/27 DwightKr Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CIDQFileList::Release( CIDQFile & idqFile )
|
||
|
{
|
||
|
idqFile.Release();
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CIDQFileList::DeleteZombies - public
|
||
|
//
|
||
|
// Synopsis: Removes IDQ files that are zombies; i.e. out of date
|
||
|
//
|
||
|
// History: 96/Mar/28 DwightKr Created.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void CIDQFileList::DeleteZombies()
|
||
|
{
|
||
|
// ==========================================
|
||
|
CLock lock( _mutex );
|
||
|
|
||
|
unsigned i=0;
|
||
|
while ( i<_aIDQFile.Count() )
|
||
|
{
|
||
|
if ( _aIDQFile[i]->LokGetRefCount() == 0 &&
|
||
|
!_aIDQFile[i]->IsCachedDataValid() )
|
||
|
{
|
||
|
CIDQFile * pIDQFile = _aIDQFile[i];
|
||
|
_aIDQFile.Remove(i);
|
||
|
|
||
|
ciGibDebugOut(( DEB_ITRACE,
|
||
|
"Deleting zombie IDQ cache entry %ws, %d entries cached\n",
|
||
|
pIDQFile->GetIDQFileName(),
|
||
|
_aIDQFile.Count() ));
|
||
|
|
||
|
delete pIDQFile;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ciGibDebugOut(( DEB_ITRACE,
|
||
|
"IDQ cache entry %ws was not deleted, refCount=%d\n",
|
||
|
_aIDQFile[i]->GetIDQFileName(),
|
||
|
_aIDQFile[i]->LokGetRefCount() ));
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ==========================================
|
||
|
}
|
||
|
|