You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
995 lines
30 KiB
995 lines
30 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997 - 2000.
|
|
//
|
|
// File: lgplist.cxx
|
|
//
|
|
// Contents: Index server wide local/global property list class.
|
|
//
|
|
// History: 05 May 1997 Alanw Created
|
|
// 27 Aug 1997 KrishnaN Moved from ixsso to querylib
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Include Files
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include <cidebug.hxx>
|
|
#include <dynstack.hxx>
|
|
#include <funypath.hxx>
|
|
#include <dblink.hxx>
|
|
#include <imprsnat.hxx>
|
|
|
|
// class declaration
|
|
|
|
CStaticPropertyList GlobalStaticList;
|
|
CPropListFile * CLocalGlobalPropertyList::_pGlobalPropListFile = 0;
|
|
CStaticMutexSem g_mtxFilePropList; // regulates access to the global file prop list.
|
|
|
|
CRegChangeEvent CGlobalPropFileRefresher::_regChangeEvent( wcsRegCommonAdminTree, TRUE );
|
|
WCHAR CGlobalPropFileRefresher::_wcsFileName[];
|
|
FILETIME CGlobalPropFileRefresher::_ftFile;
|
|
DWORD CGlobalPropFileRefresher::_dwLastCheckMoment;
|
|
BOOL CGlobalPropFileRefresher::_fInited = FALSE;
|
|
HKEY CGlobalPropFileRefresher::_hKey;
|
|
LONG CGlobalPropFileRefresher::_lRegReturn;
|
|
|
|
CGlobalPropFileRefresher gRefresher;
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CDefColumnRegEntry::CDefColumnRegEntry, public
|
|
//
|
|
// Synopsis: Constructor for registry param object
|
|
//
|
|
// Arguments: [pwcName] - 0 or name of the catalog from the registry
|
|
//
|
|
// History: 12-Oct-96 dlee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CDefColumnRegEntry::CDefColumnRegEntry()
|
|
{
|
|
// set default
|
|
wcscpy( _awcDefaultColumnFile, L"" );
|
|
|
|
} //CDefColumnRegEntry
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CDefColumnRegEntry::Refresh, public
|
|
//
|
|
// Synopsis: Reads the values from the registry
|
|
//
|
|
// History: 12-Oct-96 dlee Added header, reorganized
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CDefColumnRegEntry::Refresh( BOOL fUseDefaultsOnFailure )
|
|
{
|
|
TRY
|
|
{
|
|
// Query the registry.
|
|
|
|
CRegAccess regAdmin( RTL_REGISTRY_CONTROL, wcsRegCommonAdmin );
|
|
|
|
XPtrST<WCHAR> xRegValue(regAdmin.Read(wcsDefaultColumnFile, L""));
|
|
|
|
wcsncpy( _awcDefaultColumnFile, xRegValue.GetPointer(), MAX_PATH );
|
|
}
|
|
CATCH (CException, e)
|
|
{
|
|
// Only store defaults when told to do so -- the params
|
|
// are still in good shape at this point and are more
|
|
// accurate than the default settings.
|
|
|
|
if ( fUseDefaultsOnFailure )
|
|
wcscpy( _awcDefaultColumnFile, L"" );
|
|
}
|
|
END_CATCH
|
|
} //Refresh
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropListFile::CPropListFile
|
|
//
|
|
// Synopsis: Constructor of a property list from a file
|
|
//
|
|
// Arguments: [pDefaultList] -- The default property list
|
|
// [fDynamicRefresh] -- True, if list should be dynamically
|
|
// refreshed when file changes.
|
|
// [pwcPropFile] -- The property file. If this is null,
|
|
// use the registry.
|
|
// [ulCodePage] -- Codepage to interpret the property list.
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 08 Sep 1997 KrishnaN Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CPropListFile::CPropListFile( CEmptyPropertyList *pDefaultList,
|
|
BOOL fDynamicRefresh,
|
|
WCHAR const * pwcPropFile,
|
|
ULONG ulCodePage ) :
|
|
CCombinedPropertyList(pDefaultList, ulCodePage),
|
|
_scError( S_OK ),
|
|
_iErrorLine( 0 ),
|
|
_xErrorFile( 0 ),
|
|
_ulCodePage( ulCodePage ),
|
|
_fDynamicRefresh( fDynamicRefresh ),
|
|
_dwLastCheckMoment( GetTickCount() )
|
|
{
|
|
if (pwcPropFile)
|
|
Load(pwcPropFile);
|
|
else
|
|
{
|
|
WCHAR wszFile[MAX_PATH+1];
|
|
_RegParams.GetDefaultColumnFile( wszFile, MAX_PATH );
|
|
Load(wszFile);
|
|
}
|
|
}
|
|
|
|
CPropListFile::~CPropListFile()
|
|
{
|
|
ClearList();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropListFile::Load - public
|
|
//
|
|
// Synopsis: Loads the file into the property list.
|
|
//
|
|
// Arguments: [pwszFile] -- File name for property definitions
|
|
//
|
|
// History: 06 May 1997 AlanW Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropListFile::Load(WCHAR const * const pwszFile )
|
|
{
|
|
if (0 == pwszFile || 0 == *pwszFile)
|
|
return;
|
|
|
|
CImpersonateSystem impersonateSystem;
|
|
|
|
// prevent multiple loads at the same time
|
|
|
|
CLock lock(_mtx);
|
|
|
|
// Erase any previous error settings.
|
|
_scError = S_OK;
|
|
_iErrorLine = 0;
|
|
_xErrorFile.Free();
|
|
|
|
SCODE sc = GetLastWriteTime(pwszFile, _ftFile);
|
|
if (S_OK == sc)
|
|
{
|
|
// ParseNameFile should not throw exceptions.
|
|
sc = ParseNameFile( pwszFile );
|
|
}
|
|
else
|
|
sc = QPLIST_E_CANT_OPEN_FILE;
|
|
|
|
if (FAILED(sc))
|
|
{
|
|
qutilDebugOut(( DEB_WARN, "Can't open column file named %ws\n", pwszFile ));
|
|
_scError = sc;
|
|
_iErrorLine = 0;
|
|
|
|
if (0 == _xErrorFile.GetPointer())
|
|
{
|
|
WCHAR * pwcErrorFile = new WCHAR[wcslen(pwszFile)+1];
|
|
wcscpy(pwcErrorFile, pwszFile);
|
|
_xErrorFile.Set( pwcErrorFile );
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropListFile::IsMapUpToDate - public
|
|
//
|
|
// Synopsis: Determines if the file is still vaid, or if it has
|
|
// changed since it was last read.
|
|
//
|
|
// History: 06 May 1997 AlanW Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropListFile::IsMapUpToDate()
|
|
{
|
|
//
|
|
// Has the file been modified since last loaded?
|
|
//
|
|
|
|
FILETIME ft;
|
|
SCODE sc = GetLastWriteTime(_xFileName.GetPointer(), ft);
|
|
|
|
|
|
if (FAILED(sc))
|
|
return E_HANDLE;
|
|
|
|
if ( (_ftFile.dwLowDateTime == ft.dwLowDateTime) &&
|
|
(_ftFile.dwHighDateTime == ft.dwHighDateTime) )
|
|
return S_OK;
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CPropListFile::GetLastWriteTime, static
|
|
//
|
|
// Purpose: Gets the last change time of the file specified
|
|
//
|
|
// Arguments: [wcsFileName] - name of file to get last write time of
|
|
// [ftLastWrite] - on return, last mod. time of file
|
|
//
|
|
// Returns: SCODE - S_OK if successful.
|
|
//
|
|
// History: 96/Jan/23 DwightKr Created
|
|
// 96/Mar/13 DwightKr Changed to use GetFileAttributesEx()
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropListFile::GetLastWriteTime( WCHAR const * wcsFileName,
|
|
FILETIME & ftLastWrite )
|
|
{
|
|
if ( 0 == wcsFileName )
|
|
return E_INVALIDARG;
|
|
|
|
WIN32_FIND_DATA ffData;
|
|
|
|
if ( !GetFileAttributesEx( wcsFileName, GetFileExInfoStandard, &ffData ) )
|
|
{
|
|
ULONG error = GetLastError();
|
|
|
|
qutilDebugOut(( DEB_IERROR,
|
|
"Unable to GetFileAttributesEx(%ws) GetLastError=0x%x\n",
|
|
wcsFileName,
|
|
error ));
|
|
return HRESULT_FROM_WIN32(error);
|
|
}
|
|
|
|
ftLastWrite = ffData.ftLastWriteTime;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropListfile::ParseNameFile, public
|
|
//
|
|
// Synopsis: Parses the given file name and creates a list of 'friendly
|
|
// name' to CDbColId equivalences.
|
|
//
|
|
// Arguments: szFileName -- name of the file to parse
|
|
//
|
|
// History: 17-May-94 t-jeffc Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropListFile::ParseNameFile( WCHAR const * wcsFileName )
|
|
{
|
|
int iLength;
|
|
BOOL fRememberFileName = FALSE;
|
|
|
|
if( wcsFileName == 0 )
|
|
{
|
|
// use the last specified property file
|
|
if( !_xFileName.IsNull() )
|
|
{
|
|
wcsFileName = _xFileName.GetPointer();
|
|
iLength = wcslen( wcsFileName ) + 1;
|
|
}
|
|
else
|
|
return QPLIST_E_CANT_OPEN_FILE;
|
|
}
|
|
else
|
|
{
|
|
// make a copy of the file name
|
|
_xFileName.Free();
|
|
|
|
iLength = wcslen( wcsFileName ) + 1;
|
|
|
|
_xFileName.Set( new WCHAR[ iLength ] );
|
|
|
|
memcpy( _xFileName.GetPointer(), wcsFileName, iLength * sizeof WCHAR );
|
|
}
|
|
|
|
CSFile pfile( OpenFileFromPath( wcsFileName ) );
|
|
|
|
if( pfile == 0 )
|
|
return QPLIST_E_CANT_OPEN_FILE;
|
|
|
|
//
|
|
// Process a line at a time, skip ahead until we find the [Names]
|
|
// or [Query] section and process lines within that section only.
|
|
//
|
|
BOOL fNameSection = FALSE;
|
|
SCODE sc = S_OK;
|
|
|
|
int iLine = 0;
|
|
|
|
for( ;; )
|
|
{
|
|
TRY
|
|
{
|
|
iLine++;
|
|
|
|
// line buffers
|
|
char szLine[ MAX_LINE_LENGTH ];
|
|
WCHAR wcsLine[ MAX_LINE_LENGTH ];
|
|
|
|
if( !fgets( szLine, MAX_LINE_LENGTH, pfile ) )
|
|
{
|
|
if( feof( pfile ) )
|
|
break;
|
|
|
|
THROW( CPListException( QPLIST_E_READ_ERROR, iLine ) );
|
|
}
|
|
|
|
//
|
|
// Skip ahead until we find a [Names] section
|
|
//
|
|
if ( *szLine == '[' )
|
|
{
|
|
if ( _strnicmp(szLine, "[Names]", 7) == 0 )
|
|
{
|
|
fNameSection = TRUE;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
fNameSection = FALSE;
|
|
continue;
|
|
}
|
|
}
|
|
else if ( *szLine == '#' )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( fNameSection )
|
|
{
|
|
if( MultiByteToWideChar( _ulCodePage,
|
|
MB_COMPOSITE,
|
|
szLine,
|
|
-1,
|
|
wcsLine,
|
|
MAX_LINE_LENGTH )
|
|
== 0 )
|
|
{
|
|
THROW( CException() );
|
|
}
|
|
|
|
CQueryScanner scanner( wcsLine, FALSE );
|
|
XPtr<CPropEntry> propentry;
|
|
CPropertyList::ParseOneLine( scanner, iLine, propentry );
|
|
if (propentry.GetPointer())
|
|
{
|
|
AddEntry( propentry.GetPointer(), iLine );
|
|
propentry.Acquire();
|
|
}
|
|
}
|
|
}
|
|
CATCH( CPListException, e )
|
|
{
|
|
qutilDebugOut(( DEB_WARN,
|
|
"Plist exception %08x caught parsing default column file at line %d. Line ignored.\n",
|
|
e.GetErrorCode(), e.GetLine() ));
|
|
|
|
sc = _scError = e.GetErrorCode();
|
|
_iErrorLine = e.GetLine();
|
|
fRememberFileName = TRUE;
|
|
}
|
|
AND_CATCH ( CException, e )
|
|
{
|
|
qutilDebugOut(( DEB_WARN,
|
|
"Exception caught parsing default column file %08x\n",
|
|
e.GetErrorCode() ));
|
|
sc = _scError = e.GetErrorCode();
|
|
fRememberFileName = TRUE;
|
|
}
|
|
END_CATCH
|
|
|
|
if (fRememberFileName && 0 == _xErrorFile.GetPointer())
|
|
{
|
|
fRememberFileName = FALSE;
|
|
WCHAR * pwcErrorFile = new WCHAR[wcslen(wcsFileName)+1];
|
|
wcscpy(pwcErrorFile, wcsFileName);
|
|
_xErrorFile.Set( pwcErrorFile );
|
|
}
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropListfile::CheckError, public
|
|
//
|
|
// Synopsis: Checks if there was an error in the parsing of the file.
|
|
//
|
|
// Arguments: iLine -- error line number returned here.
|
|
// ppFile -- file name returned here. can be 0 if not needed.
|
|
//
|
|
// History: 17-Sep-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropListFile::CheckError( ULONG & iLine, WCHAR ** ppFile )
|
|
{
|
|
iLine = _iErrorLine;
|
|
if (ppFile)
|
|
*ppFile = _xErrorFile.GetPointer();
|
|
return _scError;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropListfile::Refresh, private
|
|
//
|
|
// Synopsis: Reloads the property list if prop. file has been modified.
|
|
//
|
|
// History: 15-Sep-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropListFile::Refresh()
|
|
{
|
|
if (!_fDynamicRefresh)
|
|
return;
|
|
|
|
// Don't check more than once in a few seconds
|
|
if (abs(GetTickCount() - _dwLastCheckMoment) < REFRESH_INTERVAL)
|
|
return;
|
|
_dwLastCheckMoment = GetTickCount();
|
|
|
|
if (S_OK != IsMapUpToDate())
|
|
{
|
|
//
|
|
// Reload.
|
|
//
|
|
|
|
ClearList();
|
|
Load(_xFileName.GetPointer());
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CCombinedPropertyList::Find, public
|
|
//
|
|
// Synopsis: Attempt to find an entry in the list.
|
|
//
|
|
// Arguments: wcsName -- friendly property name to find
|
|
//
|
|
// Returns a pointer to the CPropEntry if found, 0 otherwise.
|
|
//
|
|
// History: 17-May-94 t-jeffc Created.
|
|
// 28-Aug-97 KrishnaN modified.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CPropEntry const * CCombinedPropertyList::Find( WCHAR const * wcsName )
|
|
{
|
|
if( 0 == wcsName )
|
|
return 0;
|
|
|
|
//
|
|
// First look in the default list, and if not found, look
|
|
// in the overrides.
|
|
//
|
|
|
|
CPropEntry const * ppentry = _xDefaultList->Find(wcsName);
|
|
if (ppentry)
|
|
return ppentry;
|
|
|
|
return (_xOverrideList.GetPointer() ? _xOverrideList->Find(wcsName) : 0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CCombinedPropertyList::Next, public
|
|
//
|
|
// Synopsis: Gets the next property during an enumeration
|
|
//
|
|
// Returns: The next property entry or 0 for end of enumeration
|
|
//
|
|
// History: 21-Jul-97 dlee Moved from .hxx and added header
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CPropEntry const * CCombinedPropertyList::Next()
|
|
{
|
|
//
|
|
// First look in the static list, and if not found, look in the overrides.
|
|
//
|
|
|
|
CPropEntry const *pEntry = 0;
|
|
|
|
if (!_fOverrides)
|
|
pEntry = _xDefaultList->Next();
|
|
|
|
if (pEntry)
|
|
return pEntry;
|
|
|
|
_fOverrides = TRUE;
|
|
return (_xOverrideList.GetPointer() ? _xOverrideList->Next() : 0);
|
|
} //Next
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CCombinedPropertyList::InitIterator, public
|
|
//
|
|
// Synopsis: Initialize the iterator
|
|
//
|
|
// History: 29-Aug-97 KrishnaN Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCombinedPropertyList::InitIterator()
|
|
{
|
|
// causes the default list to be iterated before the overrides
|
|
|
|
_fOverrides = FALSE;
|
|
|
|
// Initialize the iterators of the two lists
|
|
|
|
_xDefaultList->InitIterator();
|
|
|
|
if (_xOverrideList.GetPointer())
|
|
_xOverrideList->InitIterator();
|
|
} //InitIterator
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CCombinedPropertyList::AddEntry, private
|
|
//
|
|
// Synopsis: Adds a CPropEntry to the overriding list. Verifies that the name
|
|
// isn't already in the default list or the overriding list.
|
|
//
|
|
// Arguments: ppentryNew -- pointer to the CPropEntry to add
|
|
// iLine -- line number we're parsing
|
|
//
|
|
// History: 11-Sep-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCombinedPropertyList::AddEntry( CPropEntry * ppentryNew, int iLine )
|
|
{
|
|
// protect _xOverrideList
|
|
CLock lock(_mtxAdd);
|
|
|
|
if (0 == _xOverrideList.GetPointer())
|
|
{
|
|
_xOverrideList.Set(new CPropertyList(_ulCodePage));
|
|
}
|
|
|
|
//
|
|
// We do not allow entries in the override list that have the same name
|
|
// as the default list.
|
|
//
|
|
|
|
if( _xDefaultList->Find( ppentryNew->GetName() ) ||
|
|
_xOverrideList->Find( ppentryNew->GetName() ) )
|
|
THROW( CPListException( QPLIST_E_DUPLICATE, iLine ) );
|
|
|
|
_xOverrideList->AddEntry(ppentryNew, iLine);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CCombinedPropertyList::ClearList, public
|
|
//
|
|
// Synopsis: Frees the memory used by the list.
|
|
//
|
|
// History: 11-Sep-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCombinedPropertyList::ClearList()
|
|
{
|
|
// protect _xOverrideList
|
|
CLock lock(_mtxAdd);
|
|
|
|
//
|
|
// Just free it now. It will be created, if necessary,
|
|
// on AddEntry().
|
|
//
|
|
|
|
_xOverrideList.Free();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CCombinedPropertyList::SetDefaultList, public
|
|
//
|
|
// Synopsis: Sets the default list.
|
|
//
|
|
// Arguments: pDefaultList -- The list to set as default list.
|
|
//
|
|
// History: 11-Sep-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCombinedPropertyList::SetDefaultList(CEmptyPropertyList *pDefaultList)
|
|
{
|
|
Win4Assert(pDefaultList);
|
|
|
|
// Jettison any existing property list
|
|
_xDefaultList.Free();
|
|
|
|
_xDefaultList.Set(pDefaultList);
|
|
pDefaultList->AddRef();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CCombinedPropertyList::GetCount, public
|
|
//
|
|
// Synopsis: Returns cardinality of list.
|
|
//
|
|
// History: 11-Sep-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
ULONG CCombinedPropertyList::GetCount()
|
|
{
|
|
ULONG ulTotal = _xDefaultList->GetCount();
|
|
if (_xOverrideList.GetPointer())
|
|
{
|
|
ulTotal += _xOverrideList->GetCount();
|
|
}
|
|
|
|
return ulTotal;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CCombinedPropertyList::GetAllEntries, public
|
|
//
|
|
// Synopsis: Returns cardinality of list.
|
|
//
|
|
// History: 11-Sep-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
SCODE CCombinedPropertyList::GetAllEntries(CPropEntry **ppPropEntries,
|
|
ULONG ulMaxCount)
|
|
{
|
|
ULONG ulSize = _xDefaultList->GetCount();
|
|
// get the first set of entries from the default list
|
|
SCODE sc = _xDefaultList->GetAllEntries(ppPropEntries, min(ulSize, ulMaxCount));
|
|
|
|
// get the remaining entries from the override list
|
|
if (S_OK == sc && ulMaxCount > ulSize && _xOverrideList.GetPointer())
|
|
{
|
|
sc = _xOverrideList->GetAllEntries(ppPropEntries+ulSize, ulMaxCount-ulSize);
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalGlobalPropertyList::CLocalGlobalPropertyList
|
|
//
|
|
// Synopsis: Constructor of a overridable file based property list.
|
|
// The file name will always be obtained through the registry.
|
|
//
|
|
// Arguments: [ulCodePage] -- Codepage to interpret the property list.
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 08 Sep 1997 KrishnaN Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CLocalGlobalPropertyList::CLocalGlobalPropertyList( ULONG ulCodePage ) :
|
|
CCombinedPropertyList(ulCodePage),
|
|
_ulCodePage( ulCodePage ),
|
|
_dwLastCheckMoment( GetTickCount() ),
|
|
_mtx()
|
|
{
|
|
XInterface<CPropListFile> xPropListFile(GetGlobalPropListFile());
|
|
SetDefaultList(xPropListFile.GetPointer());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalGlobalPropertyList::CLocalGlobalPropertyList
|
|
//
|
|
// Synopsis: Constructor of a overridable file based property list.
|
|
// The file name will always be obtained through the registry.
|
|
//
|
|
// Arguments: [pDefaultList] -- The default property list
|
|
// [fDynamicRefresh] -- True, if list should be dynamically
|
|
// refreshed when file changes.
|
|
// [pwcPropFile] -- The property file. If this is null,
|
|
// use the registry.
|
|
// [ulCodePage] -- Codepage to interpret the property list.
|
|
//
|
|
// Notes: This constructor is used by clients who use their own file based
|
|
// list instead of using the registry based file.
|
|
//
|
|
// History: 08 Sep 1997 KrishnaN Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CLocalGlobalPropertyList::CLocalGlobalPropertyList
|
|
(CEmptyPropertyList *pDefaultList,
|
|
BOOL fDynamicRefresh,
|
|
WCHAR const * pwcsPropFile,
|
|
ULONG ulCodePage) :
|
|
CCombinedPropertyList(ulCodePage),
|
|
_ulCodePage( ulCodePage ),
|
|
_dwLastCheckMoment( GetTickCount() ),
|
|
_mtx()
|
|
{
|
|
XInterface<CPropListFile> xPropListFile(
|
|
new CPropListFile(pDefaultList,
|
|
fDynamicRefresh,
|
|
pwcsPropFile,
|
|
ulCodePage));
|
|
SetDefaultList(xPropListFile.GetPointer());
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalGlobalPropertyList::IsMapUpToDate - public
|
|
//
|
|
// Synopsis: Determines if the file is still valid, or if it has
|
|
// changed since it was last read.
|
|
//
|
|
// History: 06 May 1997 AlanW Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CLocalGlobalPropertyList::IsMapUpToDate()
|
|
{
|
|
ULONG cchRequired = _RegParams.GetDefaultColumnFile( 0, 0 );
|
|
WCHAR wszFile[MAX_PATH + 1];
|
|
wszFile[0] = 0;
|
|
|
|
if ( 0 != cchRequired )
|
|
{
|
|
_RegParams.GetDefaultColumnFile( wszFile, MAX_PATH );
|
|
}
|
|
|
|
//
|
|
// If the current file and the one in the registry are not the same,
|
|
// we are outdated.
|
|
//
|
|
|
|
if (0 != _wcsicmp(_xFileName.GetPointer(), wszFile))
|
|
return S_FALSE;
|
|
|
|
//
|
|
// The filelist takes care of file modifications, so ask it
|
|
// directly if it is up to date.
|
|
//
|
|
|
|
return GetDefaultList().IsMapUpToDate();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalGlobalPropertyList::CheckError, public
|
|
//
|
|
// Synopsis: Checks if there was an error in the parsing of the file.
|
|
//
|
|
// Arguments: iLine -- error line number returned here.
|
|
// ppFile -- file name returned here. can be 0 if not needed.
|
|
//
|
|
// History: 17-Sep-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CLocalGlobalPropertyList::CheckError( ULONG & iLine, WCHAR ** ppFile )
|
|
{
|
|
return ((CPropListFile &)GetDefaultList()).CheckError(iLine, ppFile);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalGlobalPropertyList::Load - public
|
|
//
|
|
// Synopsis: Loads the file into the property list.
|
|
//
|
|
// Arguments: [pwszFile] -- File name for property definitions
|
|
//
|
|
// History: 19 Sep 1997 KrishnaN Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CLocalGlobalPropertyList::Load(WCHAR const * const pwszFile )
|
|
{
|
|
((CPropListFile &)GetDefaultList()).Load(pwszFile);
|
|
}
|
|
|
|
// Miscellaneous
|
|
|
|
CStaticPropertyList * GetGlobalStaticPropertyList()
|
|
{
|
|
GlobalStaticList.AddRef();
|
|
return &GlobalStaticList;
|
|
}
|
|
|
|
//
|
|
// Return an AddRef'd global prop file list. The caller will release
|
|
// when done using the global prop file list.
|
|
//
|
|
|
|
CPropListFile * GetGlobalPropListFile()
|
|
{
|
|
CImpersonateSystem impersonateSystem;
|
|
|
|
CLock lock(g_mtxFilePropList);
|
|
|
|
if (!CLocalGlobalPropertyList::_pGlobalPropListFile)
|
|
{
|
|
// The global property list will be controlled by CLocalGlobalPropertyList, so
|
|
// we disable its ability to refresh dynamically.
|
|
CLocalGlobalPropertyList::_pGlobalPropListFile =
|
|
new CPropListFile(GetGlobalStaticPropertyList(), FALSE);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If the refresher replaces the global property list, that would
|
|
// AddRef the newly created global proplist, so we should not AddREf
|
|
// again. If DoIt fails, no need to AddRef.
|
|
//
|
|
if (!gRefresher.DoIt())
|
|
CLocalGlobalPropertyList::_pGlobalPropListFile->AddRef();
|
|
}
|
|
|
|
Win4Assert(CLocalGlobalPropertyList::_pGlobalPropListFile);
|
|
|
|
return CLocalGlobalPropertyList::_pGlobalPropListFile;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CreateNewGlobalPropFileList - public
|
|
//
|
|
// Synopsis: Creates a new global file based property list.
|
|
//
|
|
// History: 15-Sep-1997 KrishnaN Created
|
|
//
|
|
// Notes: This function replaces the global property file list so that newer
|
|
// clients asking for the list will get an updated list (if the file has
|
|
// been modified or replaced.)
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CreateNewGlobalPropFileList(WCHAR CONST *wcsFileName)
|
|
{
|
|
CLock lock(g_mtxFilePropList);
|
|
|
|
Win4Assert(CLocalGlobalPropertyList::_pGlobalPropListFile);
|
|
|
|
// The global property list will be controlled by CLocalGlobalPropertyList, so
|
|
// we disable its ability to refresh dynamically.
|
|
CLocalGlobalPropertyList::_pGlobalPropListFile =
|
|
new CPropListFile(GetGlobalStaticPropertyList(),
|
|
FALSE,
|
|
wcsFileName);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGlobalPropFileRefresher::DoIt - public
|
|
//
|
|
// Synopsis: Creates a new global file based property list if necessary.
|
|
//
|
|
// Returns: True if refresh happened. False otherwise.
|
|
//
|
|
// History: 15-Sep-1997 KrishnaN Created
|
|
//
|
|
// Notes: This function monitors the registry and the file so the list
|
|
// can be updated if the underlying property file changes.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CGlobalPropFileRefresher::DoIt()
|
|
{
|
|
//
|
|
// We don't need to lock this because currently it is only
|
|
// being called after obtaining a lock elsewhere. If that
|
|
// changes, then a lock may be needed here.
|
|
//
|
|
|
|
// Don't check more than once in a few seconds
|
|
if (abs(GetTickCount() - _dwLastCheckMoment) < REFRESH_INTERVAL)
|
|
return FALSE;
|
|
|
|
CImpersonateSystem impersonateSystem;
|
|
|
|
if (!_fInited)
|
|
Init();
|
|
|
|
BOOL fRefresh = FALSE;
|
|
|
|
_dwLastCheckMoment = GetTickCount();
|
|
|
|
// First check the registry, then check the file itself
|
|
ULONG res = WaitForSingleObject( _regChangeEvent.GetEventHandle(), 0 );
|
|
if (WAIT_OBJECT_0 == res)
|
|
{
|
|
_regChangeEvent.Reset();
|
|
|
|
// the registry changed, but the value may not have. check that.
|
|
|
|
WCHAR wszFile[MAX_PATH];
|
|
|
|
GetDefaultColumnFile(wszFile);
|
|
|
|
// Are the file names the same?
|
|
if (0 != _wcsicmp(wszFile, _wcsFileName))
|
|
{
|
|
wcscpy(_wcsFileName, wszFile);
|
|
fRefresh = TRUE;
|
|
GetLastWriteTime(_ftFile);
|
|
}
|
|
}
|
|
|
|
if (! fRefresh)
|
|
{
|
|
FILETIME ft;
|
|
GetLastWriteTime(ft);
|
|
if ((_ftFile.dwLowDateTime != ft.dwLowDateTime) ||
|
|
(_ftFile.dwHighDateTime != ft.dwHighDateTime) )
|
|
{
|
|
_ftFile = ft;
|
|
fRefresh = TRUE;
|
|
}
|
|
}
|
|
|
|
if (fRefresh)
|
|
{
|
|
// refresh
|
|
|
|
CreateNewGlobalPropFileList(_wcsFileName);
|
|
}
|
|
|
|
return fRefresh;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGlobalPropFileRefresher::Init - public
|
|
//
|
|
// Synopsis: Initializes this class.
|
|
//
|
|
// Returns: Nothing. Can throw.
|
|
//
|
|
// History: 15-Sep-1997 KrishnaN Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CGlobalPropFileRefresher::Init()
|
|
{
|
|
_regChangeEvent.Init();
|
|
|
|
_lRegReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Root
|
|
wcsRegCommonAdminSubKey,
|
|
0, // Reserved
|
|
KEY_READ, // Access
|
|
&_hKey); // Handle
|
|
|
|
GetDefaultColumnFile(_wcsFileName);
|
|
GetLastWriteTime(_ftFile);
|
|
|
|
_fInited = TRUE;
|
|
}
|