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.
805 lines
19 KiB
805 lines
19 KiB
#include "StdAfx.h"
|
|
#include "ACShim.h"
|
|
#include <secconlib.h>
|
|
#include <shlwapi.h>
|
|
#include "reg.hxx"
|
|
|
|
// Undef PathAppend, or TSTR::PathAppend will not work
|
|
#undef PathAppend
|
|
|
|
// ProcessIISShims
|
|
//
|
|
// Open the app compat database and process all the IIS
|
|
// entries
|
|
//
|
|
BOOL
|
|
ProcessIISShims()
|
|
{
|
|
PDB hCompatDB = NULL;
|
|
BOOL bRet = TRUE;
|
|
TSTR_PATH strCompatDB;
|
|
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Processeing AppCompat DB.\n") ) );
|
|
|
|
if ( !strCompatDB.RetrieveWindowsDir() ||
|
|
!strCompatDB.PathAppend( APPCOMPAT_DBNAME ) )
|
|
{
|
|
// Failed to create path
|
|
return FALSE;
|
|
}
|
|
|
|
hCompatDB = SdbOpenDatabase( strCompatDB.QueryStr(), DOS_PATH );
|
|
|
|
if ( hCompatDB == NULL )
|
|
{
|
|
// Failed to open DB
|
|
return FALSE;
|
|
}
|
|
|
|
bRet = ProcessAppCompatDB( hCompatDB );
|
|
|
|
SdbCloseDatabase( hCompatDB );
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// ProcessAppCompatDB
|
|
//
|
|
// Loop through all of the App Compat entries, and process
|
|
// the ones that are IIS's
|
|
//
|
|
BOOL
|
|
ProcessAppCompatDB( PDB hCompatDB )
|
|
{
|
|
TAGID tagDB;
|
|
TAGID tagExe;
|
|
BOOL bRet = TRUE;
|
|
HRESULT hrCoInit;
|
|
|
|
tagDB = SdbFindFirstTag( hCompatDB, TAGID_ROOT, TAG_DATABASE );
|
|
|
|
if ( tagDB == NULL )
|
|
{
|
|
// Failed to open DB
|
|
return FALSE;
|
|
}
|
|
|
|
hrCoInit = CoInitialize( NULL );
|
|
|
|
if ( FAILED( hrCoInit ) )
|
|
{
|
|
iisDebugOut((LOG_TYPE_WARN, _T("Failed to CoInitialize to process AppCompat tag's, hr=0x%8x.\n"), hrCoInit));
|
|
return FALSE;
|
|
}
|
|
|
|
tagExe = SdbFindFirstTag( hCompatDB, tagDB, TAG_EXE );
|
|
|
|
while( tagExe != NULL )
|
|
{
|
|
if ( !ProcessExeTag( hCompatDB, tagExe ) )
|
|
{
|
|
// Failed to process tag
|
|
iisDebugOut((LOG_TYPE_WARN, _T("Failed to process AppCompat EXE tag.\n")));
|
|
bRet = FALSE;
|
|
}
|
|
|
|
// Get the next one
|
|
tagExe = SdbFindNextTag( hCompatDB, tagDB, tagExe );
|
|
}
|
|
|
|
CoUninitialize();
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// ProcessExeTag
|
|
//
|
|
// Process All of the Exe Tags that we have
|
|
//
|
|
BOOL
|
|
ProcessExeTag( PDB hCompatDB, TAGID tagExe )
|
|
{
|
|
TAGID tagExeInfo;
|
|
BOOL bRet = TRUE;
|
|
|
|
tagExeInfo = SdbGetFirstChild( hCompatDB, tagExe );
|
|
|
|
while ( tagExeInfo != NULL )
|
|
{
|
|
if ( IsIISShim( hCompatDB, tagExeInfo ) )
|
|
{
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Processing IIS Exe AppCompat Info tag.\n")));
|
|
|
|
if ( !ProcessShimTag( hCompatDB, tagExeInfo ) )
|
|
{
|
|
iisDebugOut((LOG_TYPE_WARN, _T("Failed to process AppCompat EXE Info tag.\n")));
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
// Get next tag
|
|
tagExeInfo = SdbGetNextChild( hCompatDB, tagExe, tagExeInfo );
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// ProcessShimTag
|
|
//
|
|
// Process the Shim Tag
|
|
//
|
|
BOOL
|
|
ProcessShimTag( PDB hCompatDB, TAGID tagShim )
|
|
{
|
|
TSTR_PATH strBasePath;
|
|
CExtensionList ExtenstionList;
|
|
|
|
if ( !GetBasePath( &strBasePath, hCompatDB, tagShim ) )
|
|
{
|
|
// This entry does not have a base path, so ignore
|
|
return TRUE;
|
|
}
|
|
|
|
if ( !PathIsDirectory( strBasePath.QueryStr() ) )
|
|
{
|
|
// The directory does not exist, so it must not be installed
|
|
return TRUE;
|
|
}
|
|
|
|
if ( !BuildExtensionList( hCompatDB, tagShim, strBasePath.QueryStr(), &ExtenstionList ) )
|
|
{
|
|
// Failed to construct List
|
|
return FALSE;
|
|
}
|
|
|
|
if ( ExtenstionList.DoesAnItemExist() )
|
|
{
|
|
if ( !InstallAppInMB( hCompatDB, tagShim, ExtenstionList ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// GetBasePath
|
|
//
|
|
// Get the Base Path for the Shim Tag we are talking about.
|
|
// This is either going to be a physical path or a registry entry with
|
|
// the path
|
|
//
|
|
BOOL
|
|
GetBasePath( TSTR_PATH *pstrBasePath, PDB hCompatDB, TAGID tagShim )
|
|
{
|
|
TSTR strDBPath;
|
|
TSTR strType;
|
|
|
|
ASSERT( hCompatDB != NULL );
|
|
ASSERT( tagShim != NULL );
|
|
|
|
if ( !GetValueFromName( &strDBPath, hCompatDB, tagShim, APPCOMPAT_TAG_BASEPATH ) ||
|
|
!GetValueFromName( &strType, hCompatDB, tagShim, APPCOMPAT_TAG_PATHTYPE ) )
|
|
{
|
|
// Failed to get Base Path
|
|
return FALSE;
|
|
}
|
|
|
|
if ( strType.IsEqual( APPCOMPAT_TYPE_PHYSICALPATH ) )
|
|
{
|
|
// This is a phsycial path, so expand environment variables and return
|
|
if ( !pstrBasePath->Copy( strDBPath ) ||
|
|
!pstrBasePath->ExpandEnvironmentVariables() )
|
|
{
|
|
// Failed
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// It is a registry key instead, so lets retrieve it
|
|
return GetBasePathFromRegistry( pstrBasePath, strDBPath );
|
|
}
|
|
|
|
// GetBasePathFromRegistry
|
|
//
|
|
// Retrieve the Base Path for an entry, by reading the registry key
|
|
// that contains it
|
|
//
|
|
// Parameters
|
|
// pstrBasePath - [out] The path from the registry
|
|
// strFullRegPath - [in] The registry path to check
|
|
//
|
|
BOOL
|
|
GetBasePathFromRegistry( TSTR_PATH *pstrBasePath, TSTR &strFullRegPath )
|
|
{
|
|
TSTR strRegBase;
|
|
TSTR strRegPath;
|
|
TSTR strRegName;
|
|
LPTSTR szFirstSlash;
|
|
LPTSTR szLastSlash;
|
|
|
|
szFirstSlash = _tcschr( strFullRegPath.QueryStr(), _T('\\') );
|
|
szLastSlash = _tcsrchr( strFullRegPath.QueryStr(), _T('\\') );
|
|
|
|
if ( ( szFirstSlash == NULL ) ||
|
|
( szLastSlash == NULL ) ||
|
|
( szLastSlash == szFirstSlash ) )
|
|
{
|
|
// If there are not atleast 2 '\'s then it is not a correct registry path
|
|
return FALSE;
|
|
}
|
|
|
|
// Temporarily Null terminate strings
|
|
*szFirstSlash = _T('\0');
|
|
*szLastSlash = _T('\0');
|
|
|
|
if ( !strRegBase.Copy( strFullRegPath.QueryStr() ) ||
|
|
!strRegPath.Copy( szFirstSlash + 1 ) ||
|
|
!strRegName.Copy( szLastSlash + 1 ) )
|
|
{
|
|
// Failed to copy path's
|
|
*szFirstSlash = _T('\\');
|
|
*szLastSlash = _T('\\');
|
|
return FALSE;
|
|
}
|
|
|
|
// Insert back the slashes
|
|
*szFirstSlash = _T('\\');
|
|
*szLastSlash = _T('\\');
|
|
|
|
return RetrieveRegistryString( pstrBasePath, strRegBase, strRegPath, strRegName );
|
|
}
|
|
|
|
// RetrieveRegistryString
|
|
//
|
|
// Retrieve a string from the registry
|
|
//
|
|
// Parameters:
|
|
// pstrValue - [out] The value retrieved from the registry
|
|
// strRegBase - [in] The base path, ie HKEY_LOCAL_MACHINE
|
|
// strRegPath - [in] The path to the registry key
|
|
// strRegName - [in] The name of the registry value
|
|
//
|
|
BOOL
|
|
RetrieveRegistryString( TSTR_PATH *pstrValue,
|
|
TSTR &strRegBase,
|
|
TSTR &strRegPath,
|
|
TSTR &strRegName )
|
|
{
|
|
CRegistry Reg;
|
|
HKEY hRoot;
|
|
|
|
if ( strRegBase.IsEqual( APPCOMPAT_REG_HKLM, FALSE ) )
|
|
{
|
|
hRoot = HKEY_LOCAL_MACHINE;
|
|
}
|
|
else
|
|
if ( strRegBase.IsEqual( APPCOMPAT_REG_HKCU, FALSE ) )
|
|
{
|
|
hRoot = HKEY_CURRENT_USER;
|
|
}
|
|
else
|
|
if ( strRegBase.IsEqual( APPCOMPAT_REG_HKCR, FALSE ) )
|
|
{
|
|
hRoot = HKEY_CLASSES_ROOT;
|
|
}
|
|
else
|
|
if ( strRegBase.IsEqual( APPCOMPAT_REG_HKU, FALSE ) )
|
|
{
|
|
hRoot = HKEY_USERS;
|
|
}
|
|
else
|
|
if ( strRegBase.IsEqual( APPCOMPAT_REG_HKCC, FALSE ) )
|
|
{
|
|
hRoot = HKEY_CURRENT_CONFIG;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !Reg.OpenRegistry( hRoot, strRegPath.QueryStr(), KEY_READ ) )
|
|
{
|
|
// Failed to open registry
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !Reg.ReadValueString( strRegName.QueryStr(), pstrValue ) )
|
|
{
|
|
// Failed to read string from registry
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// BuildExtensionList
|
|
//
|
|
// Build the extension list from the Compat DB for this tag
|
|
//
|
|
// Parameters:
|
|
// hCompatDB - [in] Pointer to compat DB
|
|
// tagShim - [in] Tag to process
|
|
// szBasePath - [in] Base path for these extensions
|
|
// pExtensions - [out] Extensions class to add them too
|
|
//
|
|
BOOL
|
|
BuildExtensionList( PDB hCompatDB,
|
|
TAGID tagShim,
|
|
LPTSTR szBasePath,
|
|
CExtensionList *pExtensions )
|
|
{
|
|
TSTR_PATH strExtFullPath;
|
|
TSTR strExtensions;
|
|
TSTR strIndicatorFile;
|
|
LPTSTR szExtensions;
|
|
LPTSTR szNext;
|
|
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Building extension list.\n") ) );
|
|
|
|
if ( GetValueFromName( &strIndicatorFile,
|
|
hCompatDB,
|
|
tagShim,
|
|
APPCOMPAT_TAG_SETUPINDICATOR ) )
|
|
{
|
|
// SetupIndicator File is Set
|
|
if ( !strExtFullPath.Copy( szBasePath ) ||
|
|
!strExtFullPath.PathAppend( strIndicatorFile ) ||
|
|
!pExtensions->SetIndicatorFile( strExtFullPath.QueryStr() ) )
|
|
{
|
|
// Failed to set indicator file
|
|
return FALSE;
|
|
}
|
|
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Indicator File found, it is '%s'.\n"), strExtFullPath.QueryStr() ) );
|
|
}
|
|
|
|
if ( !GetValueFromName( &strExtensions,
|
|
hCompatDB,
|
|
tagShim,
|
|
APPCOMPAT_TAG_WEBSVCEXT ) )
|
|
{
|
|
// No WebSvcExtension to retrieve
|
|
return TRUE;
|
|
}
|
|
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Building extension list with '%s'.\n"), strExtensions.QueryStr() ) );
|
|
|
|
// Get pointer to begining of list
|
|
szExtensions = strExtensions.QueryStr();
|
|
|
|
while ( szExtensions && *szExtensions )
|
|
{
|
|
szNext = _tcschr( szExtensions, _T(',') );
|
|
|
|
if ( szNext )
|
|
{
|
|
*szNext = _T('\0');
|
|
szNext++;
|
|
}
|
|
|
|
if ( !strExtFullPath.Copy( szBasePath ) ||
|
|
!strExtFullPath.PathAppend( szExtensions ) )
|
|
{
|
|
// Failed to construct path
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !pExtensions->AddItem( strExtFullPath.QueryStr(),
|
|
PathFileExists( strExtFullPath.QueryStr() ) ) )
|
|
{
|
|
// Failed to add item to list
|
|
return FALSE;
|
|
}
|
|
|
|
szExtensions = szNext;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// InstallAppInMB
|
|
//
|
|
// Installs the Application Extensions and dependencies into the metabase
|
|
// tagShim points to the Shim entry in the AppCompat DB where all App settings reside
|
|
//
|
|
BOOL
|
|
InstallAppInMB( PDB hCompatDB, TAGID tagShim, CExtensionList &ExtensionList )
|
|
{
|
|
TSTR strGroupId;
|
|
TSTR strGroupDesc;
|
|
TSTR strAppName;
|
|
TSTR strExtGroups;
|
|
TSTR strPath;
|
|
BOOL bExists;
|
|
CSecConLib Helper;
|
|
DWORD i;
|
|
BOOL bRet;
|
|
HRESULT hr;
|
|
|
|
// Ignore if we can not get this value, since it is not necessary
|
|
GetValueFromName( &strExtGroups, hCompatDB, tagShim, APPCOMPAT_DB_ENABLE_EXT_GROUPS );
|
|
|
|
if ( !GetValueFromName( &strGroupId, hCompatDB, tagShim, APPCOMPAT_DB_GROUPID ) ||
|
|
!GetValueFromName( &strGroupDesc, hCompatDB, tagShim, APPCOMPAT_DB_GROUPDESC ) ||
|
|
!GetValueFromName( &strAppName, hCompatDB, tagShim, APPCOMPAT_DB_APPNAME ) )
|
|
{
|
|
iisDebugOut( ( LOG_TYPE_PROGRAM_FLOW,
|
|
_T("Could not retrieve all values for App from DB, so will not add to RestrictionList. ('%s','%s','%s','%s')\n"),
|
|
strGroupId.QueryStr() ? strGroupId.QueryStr() : _T("<Unknown>"),
|
|
strGroupDesc.QueryStr() ? strGroupDesc.QueryStr() : _T("<Unknown>"),
|
|
strAppName.QueryStr() ? strAppName.QueryStr() : _T("<Unknown>"),
|
|
strExtGroups.QueryStr() ? strExtGroups.QueryStr() : _T("<Unknown>")) );
|
|
|
|
// Failed to retrieve value
|
|
return TRUE;
|
|
}
|
|
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW,
|
|
_T("Adding '%s' group to WebSvcRestriction List from AppCompat DB.\n"),
|
|
strGroupId.QueryStr() ) );
|
|
|
|
// Add Extensions
|
|
for ( i = 0; i < ExtensionList.QueryNumberofItems(); i++ )
|
|
{
|
|
if ( !ExtensionList.QueryItem( i, &strPath, &bExists ) )
|
|
{
|
|
// Failed to retrieve
|
|
return FALSE;
|
|
}
|
|
|
|
hr = Helper.AddExtensionFile( strPath.QueryStr(), // Path
|
|
g_pTheApp->IsUpgrade() ? true : false, // Image should be enabled
|
|
strGroupId.QueryStr(), // GroupID
|
|
FALSE, // Not UI deletable
|
|
strGroupDesc.QueryStr(),// Group description
|
|
METABASEPATH_WWW_ROOT ); // MB location
|
|
|
|
if ( FAILED( hr ) &&
|
|
( hr != HRESULT_FROM_WIN32(ERROR_DUP_NAME) ) )
|
|
{
|
|
bRet = FALSE;
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("Failed to add extension %s to group %s, hr=0x%8x\n"), strPath.QueryStr(), strGroupId.QueryStr(), hr ));
|
|
}
|
|
}
|
|
|
|
// Add Dependencies
|
|
if ( *(strGroupId.QueryStr()) != _T('\0') )
|
|
{
|
|
hr = Helper.AddDependency( strAppName.QueryStr(),
|
|
strGroupId.QueryStr(),
|
|
METABASEPATH_WWW_ROOT );
|
|
|
|
if ( FAILED( hr ) &&
|
|
( hr != HRESULT_FROM_WIN32(ERROR_DUP_NAME) ) )
|
|
{
|
|
bRet = FALSE;
|
|
iisDebugOut((LOG_TYPE_ERROR,
|
|
_T("Failed to add dependence ( App: %s on GroupID %s ), hr=0x%8x\n"),
|
|
strAppName.QueryStr(),
|
|
strGroupId.QueryStr(),
|
|
hr ));
|
|
}
|
|
}
|
|
|
|
// Add all the other "external" groups it depends on
|
|
if ( ( *strExtGroups.QueryStr() ) != _T('\0') )
|
|
{
|
|
LPTSTR szCurrentGroup = strExtGroups.QueryStr();
|
|
LPTSTR szNextGroup;
|
|
|
|
while ( szCurrentGroup && *szCurrentGroup )
|
|
{
|
|
szNextGroup = _tcschr( szCurrentGroup, _T(',') );
|
|
|
|
if ( szNextGroup )
|
|
{
|
|
*szNextGroup = _T('\0');
|
|
szNextGroup++;
|
|
}
|
|
|
|
hr = Helper.AddDependency( strAppName.QueryStr(),
|
|
szCurrentGroup,
|
|
METABASEPATH_WWW_ROOT );
|
|
|
|
if ( FAILED( hr ) &&
|
|
( hr != HRESULT_FROM_WIN32(ERROR_DUP_NAME) ) )
|
|
{
|
|
bRet = FALSE;
|
|
iisDebugOut((LOG_TYPE_ERROR,
|
|
_T("Failed to add dependence ( App: %s on Group %s ), hr = %8x\n"),
|
|
strAppName.QueryStr(),
|
|
szCurrentGroup,
|
|
hr ));
|
|
}
|
|
|
|
|
|
szCurrentGroup = szNextGroup;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// IsIISShim
|
|
//
|
|
// Is the Tag an IIS Shim Tag
|
|
//
|
|
BOOL
|
|
IsIISShim( PDB hCompatDB, TAGID tagCurrentTag )
|
|
{
|
|
TAG tagType;
|
|
TAGID tagShimName;
|
|
TSTR strTagName;
|
|
|
|
tagType = SdbGetTagFromTagID( hCompatDB, tagCurrentTag );
|
|
|
|
if ( tagType != TAG_SHIM_REF )
|
|
{
|
|
// We handle only <SHIM> tags
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !strTagName.Resize( MAX_PATH ) )
|
|
{
|
|
// Failed to widen buffer
|
|
return FALSE;
|
|
}
|
|
|
|
tagShimName = SdbFindFirstTag( hCompatDB, tagCurrentTag, TAG_NAME );
|
|
|
|
if ( tagShimName == NULL )
|
|
{
|
|
// There is not tag name, so this is not an IIS one.
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !SdbReadStringTag( hCompatDB, tagShimName, strTagName.QueryStr(), strTagName.QuerySize() ) )
|
|
{
|
|
// Failed to read string tag
|
|
return FALSE;
|
|
}
|
|
|
|
return strTagName.IsEqual( APPCOMPAT_TAG_SHIM_IIS, FALSE );
|
|
}
|
|
|
|
// GetValueFromName
|
|
//
|
|
// Frab a value out of the Database with the Name we have given
|
|
//
|
|
// Parameters:
|
|
// pstrValue - [out] The value that was in the database
|
|
// hCompatDB - [in] Handle to DB
|
|
// tagData - [in] The tag to retrieve it from
|
|
// szTagName - [in] The name of the tag to retrieve
|
|
//
|
|
BOOL
|
|
GetValueFromName( TSTR *pstrValue, PDB hCompatDB, TAGID tagData, LPCTSTR szTagName )
|
|
{
|
|
TAGID tagChild;
|
|
TAGID tagValue;
|
|
LPTSTR szValue;
|
|
|
|
tagChild = SdbFindFirstNamedTag( hCompatDB, tagData, TAG_DATA, TAG_NAME, szTagName );
|
|
|
|
if ( tagChild == NULL )
|
|
{
|
|
// Failed to find tag
|
|
return FALSE;
|
|
}
|
|
|
|
tagValue = SdbFindFirstTag( hCompatDB, tagChild, TAG_DATA_STRING );
|
|
|
|
if ( tagValue == NULL )
|
|
{
|
|
// Failed to retrieve tag
|
|
return FALSE;
|
|
}
|
|
|
|
szValue = SdbGetStringTagPtr( hCompatDB, tagValue );
|
|
|
|
if ( szValue == NULL )
|
|
{
|
|
// Not value found, so lets just set to an empty string
|
|
szValue = _T("");
|
|
}
|
|
|
|
return pstrValue->Copy( szValue );
|
|
}
|
|
|
|
// Constructor
|
|
//
|
|
//
|
|
CExtensionList::CExtensionList()
|
|
{
|
|
m_dwNumberofItems = 0;
|
|
m_pRoot = NULL;
|
|
m_bUseIndicatorFile = FALSE;
|
|
m_bIndicatorFileExists = FALSE;
|
|
}
|
|
|
|
// Destructor
|
|
//
|
|
//
|
|
CExtensionList::~CExtensionList()
|
|
{
|
|
sExtensionItem *pCurrent;
|
|
sExtensionItem *pTemp;
|
|
|
|
pCurrent = m_pRoot;
|
|
|
|
while ( pCurrent )
|
|
{
|
|
pTemp = pCurrent;
|
|
pCurrent = pCurrent->pNext;
|
|
|
|
delete pTemp;
|
|
}
|
|
|
|
m_pRoot = NULL;
|
|
m_dwNumberofItems = 0;
|
|
}
|
|
|
|
// AddItem
|
|
//
|
|
// Add an Item to the list
|
|
//
|
|
// Parameters:
|
|
// szPath - Data for item
|
|
// bExists - Data for Item
|
|
BOOL
|
|
CExtensionList::AddItem( LPTSTR szPath, BOOL bExists )
|
|
{
|
|
sExtensionItem *pNewItem;
|
|
sExtensionItem *pLastItem = NULL;
|
|
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW,
|
|
_T("Adding item '%s',0x%8x.\n"),
|
|
szPath, bExists ) );
|
|
|
|
if ( QueryNumberofItems() != 0 )
|
|
{
|
|
pLastItem = RetrieveItem( QueryNumberofItems() - 1 );
|
|
|
|
if ( pLastItem == NULL )
|
|
{
|
|
// For some read we can not get the nth item, which should exist
|
|
ASSERT( FALSE );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
pNewItem = new sExtensionItem;
|
|
|
|
if ( pNewItem == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !pNewItem->strName.Copy( szPath ) )
|
|
{
|
|
delete pNewItem;
|
|
return FALSE;
|
|
}
|
|
|
|
pNewItem->bExists = bExists;
|
|
pNewItem->pNext = NULL;
|
|
m_dwNumberofItems++;
|
|
|
|
if ( pLastItem )
|
|
{
|
|
pLastItem->pNext = pNewItem;
|
|
}
|
|
else
|
|
{
|
|
m_pRoot = pNewItem;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// QueryItem
|
|
//
|
|
// Query the Data on a particular item
|
|
//
|
|
BOOL
|
|
CExtensionList::QueryItem( DWORD dwIndex, TSTR *pstrPath, LPBOOL pbExists)
|
|
{
|
|
sExtensionItem *pCurrent;
|
|
|
|
pCurrent = RetrieveItem( dwIndex );
|
|
|
|
if ( pCurrent == NULL )
|
|
{
|
|
// That item does not exist
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !pstrPath->Copy( pCurrent->strName ) )
|
|
{
|
|
// Could not copy name
|
|
return FALSE;
|
|
}
|
|
|
|
*pbExists = pCurrent->bExists;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// QueryNumberofItems
|
|
//
|
|
// Query the number of items in the list
|
|
//
|
|
DWORD
|
|
CExtensionList::QueryNumberofItems()
|
|
{
|
|
return m_dwNumberofItems;
|
|
}
|
|
|
|
// RetrieveItem
|
|
//
|
|
// Retrieve a specific item by its index
|
|
//
|
|
sExtensionItem *
|
|
CExtensionList::RetrieveItem( DWORD dwIndex )
|
|
{
|
|
sExtensionItem *pCurrent = m_pRoot;
|
|
|
|
while ( ( pCurrent ) &&
|
|
( dwIndex != 0 ) )
|
|
{
|
|
pCurrent = pCurrent->pNext;
|
|
dwIndex--;
|
|
}
|
|
|
|
return pCurrent;
|
|
}
|
|
|
|
// DoesAnItemExist
|
|
//
|
|
// Go through all of the items in our list,
|
|
// and determine if any of them have the bExists flag
|
|
// set
|
|
//
|
|
BOOL
|
|
CExtensionList::DoesAnItemExist()
|
|
{
|
|
sExtensionItem *pCurrent = m_pRoot;
|
|
|
|
if ( m_bUseIndicatorFile )
|
|
{
|
|
// If an indicator file is used, then just use this
|
|
return m_bIndicatorFileExists;
|
|
}
|
|
|
|
while ( pCurrent )
|
|
{
|
|
if ( pCurrent->bExists )
|
|
{
|
|
// Found one that exists
|
|
return TRUE;
|
|
}
|
|
|
|
pCurrent = pCurrent->pNext;
|
|
}
|
|
|
|
// None existed
|
|
return FALSE;
|
|
}
|
|
|
|
// SetIndicatorFile
|
|
//
|
|
// If an indicator file is set, then use the fact that this is installed
|
|
// instead of checking all the other files
|
|
//
|
|
BOOL
|
|
CExtensionList::SetIndicatorFile( LPTSTR szIndicatorFile )
|
|
{
|
|
m_bUseIndicatorFile = TRUE;
|
|
|
|
m_bIndicatorFileExists = PathFileExists( szIndicatorFile );
|
|
|
|
return TRUE;
|
|
}
|