Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1057 lines
27 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name :
metabase.cxx
Abstract:
Class that is used to modify the metabase
Author:
Christopher Achille (cachille)
Project:
Internet Services Setup
Revision History:
June 2001: Created
--*/
#include "stdafx.h"
#include "iadm.h"
#include "iiscnfgp.h"
#include "mdkey.h"
#include "mdentry.h"
#include "metabase.hxx"
#include "iiscnfg.h"
#include "strfn.h"
// function: GetSizeBasedOnMetaType
//
// Returns the DataSize for an object based on its type
//
DWORD
CMetaBase::GetSizeBasedOnMetaType(DWORD dwDataType,LPTSTR szString)
{
DWORD dwRet = 0;
switch (dwDataType)
{
case DWORD_METADATA:
dwRet = 4;
break;
case STRING_METADATA:
case EXPANDSZ_METADATA:
if (szString == NULL)
{
dwRet = 0;
}
else
{
dwRet = (_tcslen((LPTSTR)szString) + 1) * sizeof(TCHAR);
}
break;
case MULTISZ_METADATA:
if (szString == NULL)
{
dwRet = 0;
}
else
{
dwRet = GetMultiStrSize((LPTSTR)szString) * sizeof(TCHAR);
}
break;
case BINARY_METADATA:
break;
}
return dwRet;
}
// function: FindStringinMultiSz
//
// Finds a string inside of a MultiSz
//
// Parameters:
// szMultiSz - The MultiSz to search
// szSearchString - The String to find
//
// Return:
// True - It was found
// False - It was not found
BOOL
CMetaBase::FindStringinMultiSz(LPTSTR szMultiSz, LPTSTR szSearchString)
{
LPTSTR szSearchCurrent;
do
{
szSearchCurrent = szSearchString;
while ( ( *szMultiSz != '\0' ) &&
( *szSearchCurrent != '\0' ) &&
( *szMultiSz == *szSearchCurrent ))
{
// While the strings are the same, and they do not hit a null terminator
szMultiSz++;
szSearchCurrent++;
}
if ( ( *szMultiSz == '\0' ) &&
( *szMultiSz == *szSearchCurrent )
)
{
// The strings matched
return TRUE;
}
while ( *szMultiSz != '\0' )
{
// Go to the end of this string
szMultiSz++;
}
// Step right past the string terminator
szMultiSz++;
} while (*szMultiSz);
return FALSE;
}
// function: VerifyParameters
//
// Verify the parameters are correct
//
BOOL
CMetaBase_SetValue::VerifyParameters(CItemList &ciParams)
{
if ( ( ( ciParams.GetNumberOfItems() == 7 ) ||
( ( ciParams.GetNumberOfItems() == 8 ) && ciParams.IsNumber(7) )
)
&&
ciParams.IsNumber(1) &&
ciParams.IsNumber(2) &&
ciParams.IsNumber(3) &&
ciParams.IsNumber(4) &&
ciParams.IsNumber(5)
)
{
return TRUE;
}
return FALSE;
}
// funtion: DoInternalWork
//
// Set a value in the metabase
//
// Parameters:
// ciList - Parameters for OpenNode, they are the following:
// 0 -Location
// 1- Id
// 2- Inheritable
// 3- UserType
// 4- DataType
// 5- Len
// 6- Value
// 7- bDontReplace - Should we replace the value if one already exists? (default==false)
BOOL
CMetaBase_SetValue::DoInternalWork(CItemList &ciParams)
{
CMDKey cmdKey;
CMDValue cmdMetaValue;
DWORD dwSize = ciParams.GetNumber(5);
BOOL bRet = TRUE;
if ( FAILED(cmdKey.OpenNode(ciParams.GetItem(0) ) ) )
{
// Could not open the key, so we fail
return FALSE;
}
if (dwSize == 0)
{
dwSize = GetSizeBasedOnMetaType(ciParams.GetNumber(4),ciParams.GetItem(6));
}
if ( ( ciParams.GetNumberOfItems() == 8 ) && ( ciParams.GetNumber(7) == 1 ) )
{
// Make sure the value does not exist yet, because we don't want to replace the old one
bRet = !cmdKey.GetData( cmdMetaValue, ciParams.GetNumber(1) );
}
if ( bRet )
{
// Set the value for this node
cmdMetaValue.SetValue(ciParams.GetNumber(1),
ciParams.GetNumber(2),
ciParams.GetNumber(3),
ciParams.GetNumber(4),
dwSize,
(LPTSTR) ciParams.GetItem(6));
bRet = cmdKey.SetData(cmdMetaValue, ciParams.GetNumber(1));
}
cmdKey.Close();
return bRet;
}
// function: GetMethodName
//
// Return the Method Name for this Class
//
LPTSTR
CMetaBase_SetValue::GetMethodName()
{
return _T("Metabase_SetValue");
}
// function: VerifyParameters
//
// Verify the parameters are correct
//
BOOL
CMetaBase_DelIDOnEverySite::VerifyParameters(CItemList &ciParams)
{
if ( ( ciParams.GetNumberOfItems() == 2 ) &&
ciParams.IsNumber(0) &&
ciParams.IsNumber(1)
)
{
return TRUE;
}
return FALSE;
}
// funtion: DoInternalWork
//
// Set a value in the metabase
//
// Parameters:
// ciList - Parameters for OpenNode, they are the following:
// 0 - Id
// 1 - Metabase Data Type
BOOL
CMetaBase_DelIDOnEverySite::DoInternalWork(CItemList &ciParams)
{
CMDKey cmdKey;
DWORD dwId = ciParams.GetNumber(0);
DWORD dwType = ciParams.GetNumber(1);
BOOL bRet;
CStringList cslpathList;
POSITION pos;
CString csPath;
WCHAR wchKeyPath[_MAX_PATH];
LPWSTR szwKeyPath = wchKeyPath;
CString csBasePath = _T("LM/W3SVC");
if ( FAILED( cmdKey.OpenNode( csBasePath ) ) )
{
// Could not open the key, so we fail
return FALSE;
}
// get datapaths on the specified ID.
if (FAILED( cmdKey.GetDataPaths( dwId, dwType, cslpathList) ))
{
// Could not GetDataPaths for this value
return FALSE;
}
// close it so that we can open the various
// other nodes that returned and delete the values from them
cmdKey.Close();
pos = cslpathList.GetHeadPosition();
while ( NULL != pos )
{
bRet = TRUE;
csPath = cslpathList.GetNext( pos );
//iisDebugOut((LOG_TYPE_TRACE,_T("%s"),csPath));
#if defined(UNICODE) || defined(_UNICODE)
szwKeyPath = csPath.GetBuffer(0);
#else
if (MultiByteToWideChar(CP_ACP, 0, (LPCSTR)csPath.GetBuffer(0), -1, (LPWSTR)wchKeyPath, _MAX_PATH)==0)
{
// We could not convert the string to wide, so lets skip this one
continue;
}
#endif
// make a special case of the "/" path
if ( wcscmp( szwKeyPath, L"/" ) != 0 )
{
//iisDebugOut((LOG_TYPE_TRACE,_T("%s -- del"),csPath));
CString csNewPath;
csNewPath = csBasePath + szwKeyPath;
if ( SUCCEEDED(cmdKey.OpenNode(csNewPath) ) )
{
if ( FAILED(cmdKey.DeleteData(dwId, dwType) ) )
{
// i guess we don't need to report it..
}
cmdKey.Close();
}
}
}
return bRet;
}
// function: GetMethodName
//
// Return the Method Name for this Class
//
LPTSTR
CMetaBase_DelIDOnEverySite::GetMethodName()
{
return _T("CMetaBase_DelIDOnEverySite");
}
// function: VerifyParameters
//
// Verify the parameters are correct
//
BOOL
CMetaBase_IsAnotherSiteonPort80::VerifyParameters(CItemList &ciParams)
{
return ( ciParams.GetNumberOfItems() == 0 );
}
// function: FindSiteUsing80
//
// Find a Site that is using port80
//
// Parameters:
// cmdKey - The key to the metabase node
// dwId - The id of the item to find.
//
// Return
// TRUE - It has been found
// FALSE - It has not been found
BOOL
CMetaBase_IsAnotherSiteonPort80::SearchMultiSzforPort80(CMDKey &cmdKey, DWORD dwId)
{
CStringList cslpathList;
POSITION pos;
CString csPath;
CMDValue cmdValue;
WCHAR wchKeyPath[_MAX_PATH];
LPWSTR szwKeyPath = wchKeyPath;
if (FAILED( cmdKey.GetDataPaths( dwId, MULTISZ_METADATA, cslpathList) ))
{
// Could not GetDataPaths for this value
return FALSE;
}
pos = cslpathList.GetHeadPosition();
while ( NULL != pos )
{
csPath = cslpathList.GetNext( pos );
#if defined(UNICODE) || defined(_UNICODE)
szwKeyPath = csPath.GetBuffer(0);
#else
if (MultiByteToWideChar(CP_ACP, 0, (LPCSTR)csPath.GetBuffer(0), -1, (LPWSTR)wchKeyPath, _MAX_PATH)==0)
{
// We could not convert the string to wide, so lets skip this one
continue;
}
#endif
if ( ( wcscmp( szwKeyPath, L"/1/" ) != 0 ) &&
( cmdKey.GetData( cmdValue, dwId, szwKeyPath ) ) &&
( cmdValue.GetDataType() == MULTISZ_METADATA ) &&
( FindStringinMultiSz( (LPTSTR) cmdValue.GetData(), _T(":80:") ) )
)
{
if ( ( !cmdKey.GetData( cmdValue, MD_SERVER_AUTOSTART, szwKeyPath ) ) ||
( !cmdValue.IsEqual( DWORD_METADATA, 4, (DWORD) 0 ) )
)
{
// If GetData failed, or it succedded and the value is not 0, then we
// have found a match.
return TRUE;
break;
}
}
}
return FALSE;
}
// function: IsAnotherSiteonPort80
//
// Reports back whether another site besides /W3SVC/1 is configured to bind to port 80
// AND has AutoStart set to True
//
// Parameters
// None
//
// Return
// TRUE - Another site is running on port 80
// FALSE - No other site is running on port 80
BOOL
CMetaBase_IsAnotherSiteonPort80::DoInternalWork(CItemList &ciList)
{
BOOL bRet = FALSE;
CMDKey cmdKey;
if ( FAILED( cmdKey.OpenNode( _T("LM/W3SVC") ) ) )
{
// Could not open the w3svc node
return FALSE;
}
if ( SearchMultiSzforPort80( cmdKey, MD_SERVER_BINDINGS) ||
SearchMultiSzforPort80( cmdKey, MD_SECURE_BINDINGS)
)
{
bRet = TRUE;
}
cmdKey.Close();
return bRet;
}
// function: GetMethodName
//
// Return the Method Name for this Class
//
LPTSTR
CMetaBase_IsAnotherSiteonPort80::GetMethodName()
{
return _T("Metabase_IsAnotherSiteonPort80");
}
// function: VerifyParameters
//
// Verify the parameters are correct
//
BOOL
CMetaBase_VerifyValue::VerifyParameters(CItemList &ciParams)
{
if ( ( ciParams.GetNumberOfItems() == 5 ) &&
ciParams.IsNumber(1) &&
ciParams.IsNumber(2)
)
{
return TRUE;
}
return FALSE;
}
// function: GetMethodName
//
// Return the Method Name for this Class
//
LPTSTR
CMetaBase_VerifyValue::GetMethodName()
{
return _T("Metabase_VerifyValue");
}
// function: VerifyValue::DoWork
//
// Verify that the value in the particular metabase location, matches the
// value in param[4]. If it does, return true.
//
// Parameters
// 0 - Metabase Location
// 1 - Metabase Id
// 2 - Metabase Data Type
// 3 - Data Length = 0 (default value is 0 (must calculate))
// 4 - Metabase Value
//
// Return
// TRUE - The values match
// FALSE - The values do not match
BOOL
CMetaBase_VerifyValue::DoInternalWork(CItemList &ciList)
{
CMDKey cmdKey;
CMDValue cmdValue;
DWORD dwSize = ciList.GetNumber(3);
BOOL bRet = FALSE;
if ( FAILED( cmdKey.OpenNode( ciList.GetItem(0) ) ) )
{
// Could not open the w3svc node
return FALSE;
}
if (dwSize == 0)
{
dwSize = GetSizeBasedOnMetaType(ciList.GetNumber(2),ciList.GetItem(4));
}
if ( cmdKey.GetData( cmdValue, ciList.GetNumber(1) ) )
{
if ( ( ( ciList.GetNumber(2) == DWORD_METADATA ) &&
( cmdValue.IsEqual( ciList.GetNumber(2), dwSize, (DWORD) ciList.GetNumber(4) ) )
) ||
( ( ciList.GetNumber(2) != DWORD_METADATA ) &&
( cmdValue.IsEqual( ciList.GetNumber(2), dwSize, (LPVOID) ciList.GetItem(4) ) )
)
)
{
bRet = TRUE;
}
}
cmdKey.Close();
return bRet;
}
// function: GetMethodName
//
// Return the Method Name for this Class
//
LPTSTR
CMetaBase_ImportRestrictionList::GetMethodName()
{
return _T("Metabase_ImportRestrictionList");
}
// function: VerifyParameters
//
// Verify the parameters are correct
//
BOOL
CMetaBase_ImportRestrictionList::VerifyParameters(CItemList &ciParams)
{
return ( (ciParams.GetNumberOfItems() == 3) &&
( ciParams.IsNumber(1) )
);
}
// function: CreateMultiSzFromList
//
// Create a MultiSz from a List of comman delim items. So, take
// <deny/allow>,<CGI Executable>,<CGI Executable>,... (ie. "0","c:\inetpub\scripts\mycgi.exe","c:\inetpub\scripts\pagecount.exe")
// and convert to
// <0/1>\0<CGI Executable>\0<CGI Executable>\0\0 (ie. 0\0c:\inetpub\scripts\mycgi.exe\0c:\inetpub\scripts\pagecount.exe\0\0)
//
// Parameters:
// pBuff [out] - BUFFER class that is used to store the multisz
// pdwRetSize [out] - The size of the multisz that was created (in Bytes, not chars)
// szItems [in] - List of Items to put in MultiSz
// cDelimeter [in[ - The delimeter for the list
//
// Return Values
// TRUE - Successfull
// FALSE - It failed to construct MultiSz
BOOL
CMetaBase_ImportRestrictionList::CreateMultiSzFromList(BUFFER *pBuff, DWORD *pdwRetSize, LPTSTR szItems, TCHAR cDelimeter)
{
LPTSTR szSource;
LPTSTR szDest;
BOOL bInQuotes = FALSE;
// Fail if we don't have a string, or can not get a big enought buffer
if ( ( !szItems ) ||
( !pBuff->Resize( ( _tcslen( szItems ) + 2 ) * sizeof(TCHAR) ) ) // Add 2, one for string term, and one for multisz term
)
{
return FALSE;
}
szSource = szItems;
szDest = (LPTSTR) pBuff->QueryPtr();
while ( *szSource )
{
if ( *szSource == '"' )
{
bInQuotes = !bInQuotes;
}
else if ( ( *szSource == cDelimeter ) && !bInQuotes )
{
if ( ( szDest != pBuff->QueryPtr() ) &&
( *(szDest - 1) != '\0')
)
{
*szDest = '\0';
szDest++;
}
}
else
{
*szDest = *szSource;
szDest++;
}
szSource++;
}
// Lets make sure that the last string was terminated.
if ( ( szDest != pBuff->QueryPtr() ) &&
( *(szDest - 1) != '\0')
)
{
// Terminate last string
*szDest = '\0';
szDest++;
}
// Terminate MultiSz, and calc length
*szDest++ = '\0';
*pdwRetSize = (DWORD) (DWORD_PTR) (((LPBYTE) szDest) - ((LPBYTE) pBuff->QueryPtr()));
return TRUE;
}
BOOL
CMetaBase_ImportRestrictionList::ExpandEnvVar(BUFFER *pBuff)
{
BUFFER buffOriginal;
DWORD dwLength;
if ( _tcsstr( (LPTSTR) pBuff->QueryPtr(), _T("%") ) == NULL )
{
// There are no environment variables, so we can return
return TRUE;
}
if ( !buffOriginal.Resize( pBuff->QuerySize() ) )
{
// Could not resize oringal big enough
return FALSE;
}
memcpy(buffOriginal.QueryPtr(), pBuff->QueryPtr(), pBuff->QuerySize());
dwLength = ExpandEnvironmentStrings( (LPTSTR) buffOriginal.QueryPtr(), NULL, 0);
if ( ( dwLength == 0 ) ||
( !pBuff->Resize( dwLength * sizeof(TCHAR) ) )
)
{
// Something failed in ExpandEnvironmentStrings
return FALSE;
}
dwLength = ExpandEnvironmentStrings( (LPTSTR) buffOriginal.QueryPtr(), (LPTSTR) pBuff->QueryPtr() , pBuff->QuerySize() );
if ( (dwLength != 0) && (dwLength <= pBuff->QuerySize() ) )
{
// It worked
return TRUE;
}
return FALSE;
}
// function: DoInternalWork
//
// Import the RestrictionList
//
// Parameters:
// 0 - The name of the item in the inf
// 1 - The id
// 2 - The Default value (MultiSz with ';' as seperator)
//
BOOL
CMetaBase_ImportRestrictionList::DoInternalWork(CItemList &ciParams)
{
CMDKey cmdKey;
CMDValue cmdMetaValue;
BUFFER buffImportList;
DWORD dwImportList;
LPTSTR szList = NULL;
INFCONTEXT Context;
BOOL bRet = FALSE;
BOOL bForceSetting = FALSE;
if (g_pTheApp->m_fUnattended)
{
// If unattended, then look in unattend file for correct line
if ( SetupFindFirstLine_Wrapped(g_pTheApp->m_hUnattendFile, UNATTEND_FILE_SECTION, ciParams.GetItem(0), &Context) )
{
DWORD dwRequiredSize = 0;
BUFFER buffUnattend;
BUFFER buffUnattendExpanded;
if ( SetupGetLineText( &Context, INVALID_HANDLE_VALUE, NULL, NULL, NULL, 0, &dwRequiredSize) )
{
if ( ( buffUnattend.Resize( ( dwRequiredSize + 1 ) * sizeof(TCHAR) ) ) &&
( SetupGetLineText( &Context, INVALID_HANDLE_VALUE, NULL, NULL, (LPTSTR) buffUnattend.QueryPtr(), buffUnattend.QuerySize()/sizeof(TCHAR), NULL) ) &&
( ExpandEnvVar( &buffUnattend ) ) &&
( CreateMultiSzFromList( &buffImportList, &dwImportList, (LPTSTR) buffUnattend.QueryPtr(), RESTRICTIONLIST_DELIMITER ) )
)
{
szList = (LPTSTR) buffImportList.QueryPtr();
bForceSetting = TRUE;
}
}
}
}
if ( !szList )
{
// If it could not be retrieved, set it to the default.
if ( ( buffImportList.Resize(( _tcslen( ciParams.GetItem(2) ) + 2 ) * sizeof(TCHAR) ) ) &&
( CreateMultiSzFromList( &buffImportList, &dwImportList, ciParams.GetItem(2), RESTRICTIONLIST_DELIMITER) )
)
{
szList = (LPTSTR) buffImportList.QueryPtr();
}
}
if ( szList == NULL )
{
return FALSE;
}
// Set Value
if ( FAILED(cmdKey.OpenNode( _T("LM/W3SVC") ) ) )
{
// Could not open the key, so we fail
return FALSE;
}
if ( bForceSetting ||
!cmdKey.GetData(cmdMetaValue, ciParams.GetNumber(1) )
)
{
// Set the value for this node
if ( cmdMetaValue.SetValue( ciParams.GetNumber(1), // ID
0x0, // Attributes (Not inheritable)
IIS_MD_UT_SERVER, // UType
MULTISZ_METADATA, // DType
dwImportList, // Size
(LPTSTR) szList)
)
{
bRet = cmdKey.SetData(cmdMetaValue, ciParams.GetNumber(1));
}
}
cmdKey.Close();
return bRet;
}
// function: GetMethodName
//
// Return the Method Name for this Class
//
LPTSTR
CMetaBase_UpdateCustomDescList::GetMethodName()
{
return _T("Metabase_UpdateCustomDescList");
}
// function: VerifyParameters
//
// Verify the parameters are correct
//
BOOL
CMetaBase_UpdateCustomDescList::VerifyParameters(CItemList &ciParams)
{
return ( (ciParams.GetNumberOfItems() == 3) &&
( ciParams.IsNumber(1) )
);
}
// function: CreateMultiSzFromList
//
// Create a MultiSz from a List of comman delim items. So, take
// <deleteable/not deleteable>,<description>,<filepath>,... (ie. "1","asp scripts","c:\winnt\system32\inetsrv\asp.dll")
// and convert to
// <0/1>\0<description>\0<filepath>\0\0 (ie. 1\0asp scripts\0c:\winnt\system32\inetsrv\asp.dll\0\0)
//
// Parameters:
// pBuff [out] - BUFFER class that is used to store the multisz
// pdwRetSize [out] - The size of the multisz that was created (in Bytes, not chars)
// szItems [in] - List of Items to put in MultiSz
// cDelimeter [in[ - The delimeter for the list
//
// Return Values
// TRUE - Successfull
// FALSE - It failed to construct MultiSz
BOOL
CMetaBase_UpdateCustomDescList::CreateMultiSzFromList(BUFFER *pBuff, DWORD *pdwRetSize, LPTSTR szItems, TCHAR cDelimeter)
{
LPTSTR szSource;
LPTSTR szDest;
BOOL bInQuotes = FALSE;
// Fail if we don't have a string, or can not get a big enought buffer
if ( ( !szItems ) ||
( !pBuff->Resize( ( _tcslen( szItems ) + 2 ) * sizeof(TCHAR) ) ) // Add 2, one for string term, and one for multisz term
)
{
return FALSE;
}
szSource = szItems;
szDest = (LPTSTR) pBuff->QueryPtr();
while ( *szSource )
{
if ( *szSource == '"' )
{
bInQuotes = !bInQuotes;
}
else if ( ( *szSource == cDelimeter ) && !bInQuotes )
{
if ( ( szDest != pBuff->QueryPtr() ) &&
( *(szDest - 1) != '\0')
)
{
*szDest = '\0';
szDest++;
}
}
else
{
*szDest = *szSource;
szDest++;
}
szSource++;
}
// Lets make sure that the last string was terminated.
if ( ( szDest != pBuff->QueryPtr() ) &&
( *(szDest - 1) != '\0')
)
{
// Terminate last string
*szDest = '\0';
szDest++;
}
// Terminate MultiSz, and calc length
*szDest++ = '\0';
*pdwRetSize = (DWORD) (DWORD_PTR) (((LPBYTE) szDest) - ((LPBYTE) pBuff->QueryPtr()));
return TRUE;
}
BOOL
CMetaBase_UpdateCustomDescList::ExpandEnvVar(BUFFER *pBuff)
{
BUFFER buffOriginal;
DWORD dwLength;
if ( _tcsstr( (LPTSTR) pBuff->QueryPtr(), _T("%") ) == NULL )
{
// There are no environment variables, so we can return
return TRUE;
}
if ( !buffOriginal.Resize( pBuff->QuerySize() ) )
{
// Could not resize oringal big enough
return FALSE;
}
memcpy(buffOriginal.QueryPtr(), pBuff->QueryPtr(), pBuff->QuerySize());
dwLength = ExpandEnvironmentStrings( (LPTSTR) buffOriginal.QueryPtr(), NULL, 0);
if ( ( dwLength == 0 ) ||
( !pBuff->Resize( dwLength * sizeof(TCHAR) ) )
)
{
// Something failed in ExpandEnvironmentStrings
return FALSE;
}
dwLength = ExpandEnvironmentStrings( (LPTSTR) buffOriginal.QueryPtr(), (LPTSTR) pBuff->QueryPtr() , pBuff->QuerySize()/sizeof(TCHAR) );
if ( (dwLength != 0) &&
(dwLength <= ( pBuff->QuerySize()/sizeof(TCHAR) ) ) )
{
// It worked
return TRUE;
}
return FALSE;
}
// function: DoInternalWork
//
// Import the RestrictionList
//
// Parameters:
// 0 - The name of the item in the inf
// 1 - The id
// 2 - The Default value (MultiSz with ';' as seperator)
//
BOOL
CMetaBase_UpdateCustomDescList::DoInternalWork(CItemList &ciParams)
{
CMDKey cmdKey;
CMDValue cmdMetaValue;
BUFFER buffMyList;
DWORD dwMyList;
LPTSTR szList = NULL;
INFCONTEXT Context;
BOOL bRet = FALSE;
BOOL bForceSetting = FALSE;
if (g_pTheApp->m_fUnattended)
{
// If unattended, then look in unattend file for correct line
if ( SetupFindFirstLine_Wrapped(g_pTheApp->m_hUnattendFile, UNATTEND_FILE_SECTION, ciParams.GetItem(0), &Context) )
{
DWORD dwRequiredSize = 0;
BUFFER buffUnattend;
BUFFER buffUnattendExpanded;
if ( SetupGetLineText( &Context, INVALID_HANDLE_VALUE, NULL, NULL, NULL, 0, &dwRequiredSize) )
{
if ( ( buffUnattend.Resize( ( dwRequiredSize + 1 ) * sizeof(TCHAR) ) ) &&
( SetupGetLineText( &Context, INVALID_HANDLE_VALUE, NULL, NULL, (LPTSTR) buffUnattend.QueryPtr(), buffUnattend.QuerySize()/sizeof(TCHAR), NULL) ) &&
( ExpandEnvVar( &buffUnattend ) ) &&
( CreateMultiSzFromList( &buffMyList, &dwMyList, (LPTSTR) buffUnattend.QueryPtr(), CUSTOMDESCLIST_DELIMITER ) )
)
{
szList = (LPTSTR) buffMyList.QueryPtr();
bForceSetting = TRUE;
}
}
}
}
if ( !szList )
{
// If it could not be retrieved, set it to the default.
if ( ( buffMyList.Resize(( _tcslen( ciParams.GetItem(2) ) + 2 ) * sizeof(TCHAR) ) ) &&
( CreateMultiSzFromList( &buffMyList, &dwMyList, ciParams.GetItem(2), CUSTOMDESCLIST_DELIMITER) )
)
{
szList = (LPTSTR) buffMyList.QueryPtr();
}
}
if ( szList == NULL )
{
return FALSE;
}
// Set Value
if ( FAILED(cmdKey.OpenNode( _T("LM/W3SVC") ) ) )
{
// Could not open the key, so we fail
return FALSE;
}
// See if there is an existing value...
// if there is then update the value with this one...
// otherwise set it.
CStringList cslMyNewAdditions;
if (ERROR_SUCCESS != ConvertDoubleNullListToStringList(szList,cslMyNewAdditions,-1))
{
bForceSetting = TRUE;
}
// get the data
DWORD dwAttributes = 0;
DWORD dwMDDataType = MULTISZ_METADATA;
CStringList cslMyOriginalList;
if (bForceSetting || FAILED(cmdKey.GetMultiSzAsStringList(ciParams.GetNumber(1),&dwMDDataType,&dwAttributes,cslMyOriginalList)))
{
// do a fresh entry...
// Set the value for this node
if ( cmdMetaValue.SetValue(ciParams.GetNumber(1), // ID
0x0, // Attributes (Not inheritable)
IIS_MD_UT_SERVER, // UType
MULTISZ_METADATA, // DType
dwMyList, // Size
(LPTSTR) szList)
)
{
bRet = cmdKey.SetData(cmdMetaValue, ciParams.GetNumber(1));
}
}
else
{
// able to get it...so let's update it.
// loop thru it and see if our entry is already in it...
CString csNewEntryPart1;
CString csNewEntryPart2;
CString csNewEntryPart3;
CString csExistingFilePath;
BOOL bItsInTheListAlready = FALSE;
BOOL bSomethingChanged = FALSE;
POSITION pos = cslMyNewAdditions.GetHeadPosition();
POSITION pos2 = NULL;
while (pos)
{
bItsInTheListAlready = FALSE;
// get the next value
csNewEntryPart1 = cslMyNewAdditions.GetNext(pos);
if (!pos){break;}
csNewEntryPart2 = cslMyNewAdditions.GetNext(pos);
if (!pos){break;}
csNewEntryPart3 = cslMyNewAdditions.GetNext(pos);
// see if this value is in our list...
pos2 = cslMyOriginalList.GetHeadPosition();
while (pos2)
{
// get the next value
cslMyOriginalList.GetNext(pos2);
if (!pos2){break;}
csExistingFilePath = cslMyOriginalList.GetNext(pos2);
if (!pos2){break;}
// compare with other value
//iisDebugOut((LOG_TYPE_TRACE,_T("UpdateCustomDescList:%s,%s"),csNewEntryPart2,csExistingFilePath));
if (0 == _tcsicmp(csNewEntryPart2,csExistingFilePath))
{
// it's found in there!
bItsInTheListAlready = TRUE;
break;
}
cslMyOriginalList.GetNext(pos2);
}
if (FALSE == bItsInTheListAlready)
{
// Add it to the end of the list
cslMyOriginalList.AddTail(csNewEntryPart1);
cslMyOriginalList.AddTail(csNewEntryPart2);
cslMyOriginalList.AddTail(csNewEntryPart3);
bSomethingChanged = TRUE;
}
}
if (TRUE == bSomethingChanged)
{
bRet = FALSE;
if (ERROR_SUCCESS == cmdKey.SetMultiSzAsStringList(ciParams.GetNumber(1),MULTISZ_METADATA,0x0,cslMyOriginalList))
{
bRet = TRUE;
}
}
}
cmdKey.Close();
return bRet;
}