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.
3757 lines
116 KiB
3757 lines
116 KiB
//***************************************************************
|
|
// IISSCO50.cpp : Implementation of CIISSCO50
|
|
// Author: Russ Gibfried
|
|
//***************************************************************
|
|
|
|
#include "stdafx.h"
|
|
#include "IISSCOv50.h"
|
|
#include "IISSCO50.h"
|
|
|
|
#include "macrohelpers.h"
|
|
|
|
#include "MessageFile\message.h"
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50
|
|
// Provider Action handlers should be implemented here with the following prototypes:
|
|
// HRESULT CIISSCO50::Action();
|
|
// HRESULT CIISSCO50::ActionRollback();
|
|
|
|
HRESULT CIISSCO50::FinalConstruct( )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
LONG lRes;
|
|
HKEY hkey = NULL;
|
|
WCHAR szLibReg[1024];
|
|
DWORD dwPathSize = 0;
|
|
|
|
// Open the registry key where IISScoMessageFile.dll (in EventLog)
|
|
lRes = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
|
|
L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\IISSCOv50",
|
|
0, KEY_ALL_ACCESS, &hkey );
|
|
|
|
if (lRes != ERROR_SUCCESS)
|
|
goto LocalCleanup;
|
|
|
|
// Get the Path size of EventMessageFile.
|
|
lRes = RegQueryValueEx( hkey, L"EventMessageFile", NULL,
|
|
NULL, NULL, &dwPathSize );
|
|
|
|
if (lRes != ERROR_SUCCESS)
|
|
goto LocalCleanup;
|
|
|
|
// Get the value of EventMessageFile. This is set when IISScoMessageFile.dll is registered
|
|
lRes = RegQueryValueEx( hkey, L"EventMessageFile", NULL,
|
|
NULL, (LPBYTE)szLibReg, &dwPathSize );
|
|
|
|
if (lRes != ERROR_SUCCESS)
|
|
goto LocalCleanup;
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
g_ErrorModule = LoadLibrary( szLibReg );
|
|
|
|
if (g_ErrorModule == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
|
|
LocalCleanup:
|
|
|
|
RegCloseKey( hkey );
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::CreateWebSite_Execute
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters an action
|
|
// tag: CreateWebSite. Code creates and IIS 5 web site
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::CreateWebSite_Execute( IXMLDOMNode *pXMLNode )
|
|
{
|
|
|
|
TRACE_ENTER(L"CIISSCO50::CreateWebSite");
|
|
|
|
CComBSTR bWebADsPath; // adsPath: IIS://server/W3SVC
|
|
CComBSTR bstrRoot; // root directory path: c:/inetpub
|
|
CComBSTR bstrServer; // Server name; localhost if black
|
|
CComBSTR bstrSiteName; // site name; www.mysite.com
|
|
CComBSTR bstrHost; // Web Hostname
|
|
CComBSTR bstrPort; // Web port number
|
|
CComBSTR bstrIP; // Web IP address
|
|
CComBSTR bstrSBindings; // Server bindings: IP:Post:HostName
|
|
CComBSTR bServerNumber; // WebSite number: 3
|
|
//CComBSTR bFilePermissions; // File permissions: domain\user:F
|
|
CComBSTR bstrStart; // Start site when done? TRUE/FALSE
|
|
CComBSTR bstrConfigPath; // Created sites ADsPath: /W3SVC/3
|
|
CComPtr<IXMLDOMNode> pNode; // xml node <website>
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Get node in format: <executeData><Website number=''><Root />...
|
|
hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
|
|
|
|
// Debug code to view passed in Node
|
|
CComBSTR bstrDebug;
|
|
hr = pNode->get_xml(&bstrDebug);
|
|
ATLTRACE(_T("\t>>> xml = : %ls\n"), bstrDebug.m_str);
|
|
|
|
|
|
// Get properties from XML
|
|
hr = GetInputAttr(pNode, L"./Website", L"number", bServerNumber);
|
|
hr = GetInputParam(pNode,L"./Website/Root", bstrRoot);
|
|
hr = GetInputParam(pNode,L"./Website/Server", bstrServer);
|
|
hr = GetInputParam(pNode,L"./Website/SiteName", bstrSiteName);
|
|
hr = GetInputParam(pNode,L"./Website/HostName", bstrHost);
|
|
hr = GetInputParam(pNode,L"./Website/PortNumber", bstrPort);
|
|
hr = GetInputParam(pNode,L"./Website/IPAddress", bstrIP);
|
|
hr = GetInputParam(pNode,L"./Website/StartOnCreate", bstrStart);
|
|
//hr = GetInputParam(pNode,L"./Website/FilePermissions", bFilePermissions);
|
|
|
|
// Create a IIS metabase path. ex. IIS://localhost/W3SVC
|
|
bWebADsPath = IIS_PREFIX;
|
|
if ( bstrServer.Length() == 0 )
|
|
bstrServer = IIS_LOCALHOST;
|
|
|
|
bWebADsPath.AppendBSTR(bstrServer);
|
|
bWebADsPath.Append(IIS_W3SVC);
|
|
|
|
|
|
|
|
// Step .5: If port number missing, set to default (ie, 80)
|
|
if ( bstrPort.Length() == 0 )
|
|
bstrPort = IIS_DEFAULT_WEB_PORT;
|
|
|
|
if ( IsPositiveInteger(bstrPort) )
|
|
{
|
|
|
|
// Step 1: Create the ServerBinding string then check bindings to make sure
|
|
// there is not a duplicate server
|
|
hr = CreateBindingString(bstrIP, bstrPort, bstrHost, bstrSBindings);
|
|
|
|
hr = CheckBindings(bWebADsPath, bstrSBindings);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
|
|
// Step 2: Get Next available Server Number
|
|
if ( bServerNumber.Length() == 0 )
|
|
hr = GetNextIndex(bWebADsPath,bServerNumber);
|
|
|
|
// Step 3: Create the Web Site on given path, ServerNumber.
|
|
if (SUCCEEDED(hr)) hr = CreateIIs50Site(IIS_IISWEBSERVER,bWebADsPath, bServerNumber, bstrConfigPath);
|
|
IIsScoLogFailure();
|
|
|
|
// Step 4: Create a Virtual directory on new IIsWebServer configPath
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrVDirAdsPath;
|
|
hr = CreateIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath,L"ROOT", L"Default Application", bstrRoot, bstrVDirAdsPath);
|
|
IIsScoLogFailure();
|
|
|
|
// Step 5: set each property; ie, server bindings
|
|
|
|
// Bind to ADs object
|
|
CComPtr<IADs> pADs;
|
|
if (SUCCEEDED(hr)) hr = ADsGetObject(bstrConfigPath, IID_IADs, (void**) &pADs );
|
|
if ( FAILED(hr) )
|
|
{
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Set "ServerComment" property
|
|
if (SUCCEEDED(hr) && bstrSiteName.Length() > 0 )
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerComment", bstrSiteName);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Set "ServerBindings" property
|
|
if (SUCCEEDED(hr)) hr = SetMetaPropertyValue(pADs, L"ServerBindings", bstrSBindings);
|
|
IIsScoLogFailure();
|
|
|
|
|
|
// Step 6: Start Server if required IIS_FALSE
|
|
bstrStart.ToUpper();
|
|
if ( SUCCEEDED(hr) && !StringCompare(bstrStart, IIS_FALSE) )
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_TRUE);
|
|
IIsScoLogFailure();
|
|
|
|
hr = IIsServerAction(bstrConfigPath,start);
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_FALSE);
|
|
IIsScoLogFailure();
|
|
|
|
}
|
|
|
|
|
|
// Step 7: write output to ConfigPath node <ConfigPath>/W3SVC/n</ConfigPath>
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
CComBSTR bstrXML1 = IIS_W3SVC;
|
|
bstrXML1.Append(L"/");
|
|
bstrXML1.AppendBSTR(bServerNumber.m_str);
|
|
|
|
// Helper function to write to DOM
|
|
hr = PutElement(pNode, L"./Website/ConfigPath", bstrXML1.m_str);
|
|
IIsScoLogFailure();
|
|
|
|
|
|
}
|
|
// If there is a failure, then deleted the web site created in step 3
|
|
else
|
|
{
|
|
// First delete any webseites that were created in the method. Do this here because a RollBack
|
|
// will only get called on a completed previous <step>, not a failed step.
|
|
DeleteIIs50Site(IIS_IISWEBSERVER,bWebADsPath,bServerNumber);
|
|
}
|
|
|
|
} // end if Step 4
|
|
|
|
} // end if 'CheckBindings'
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_PORTNUMBER_NOT_VALID;
|
|
}
|
|
|
|
// If there is a failure.
|
|
if ( FAILED(hr) )
|
|
{
|
|
// Log failure.
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
// WebSite successfully created. Set Rollback data incase another step fails
|
|
// a a ROllBack is initiated.
|
|
CComVariant varData1(bWebADsPath);
|
|
CComVariant varData2(bServerNumber);
|
|
hr = m_pProvHelper->SetRollbackData(IIS_ROLL_ADSPATH, varData1);
|
|
hr = m_pProvHelper->SetRollbackData(IIS_ROLL_SERVERNUMBER, varData2);
|
|
}
|
|
|
|
|
|
TRACE_EXIT(L"CIISSCO50::CreateWebSite");
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::CreateWebSite_Rollback
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters a failure during
|
|
// 'CreateWebSite'. The Rollback deletes the WebSite if it exists.
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::CreateWebSite_Rollback( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::CreateWebSiteRollback");
|
|
|
|
HRESULT hr = S_OK;
|
|
CComBSTR bWebADsPath; // AdsPath: IIS://server/W3SVC
|
|
CComBSTR bServerNumber; // Web server number
|
|
CComBSTR bstrConfigPath; // Complete ADsPath to check: IIS://localhost/W3SVC/1
|
|
|
|
|
|
CComVariant varWebADsPath;
|
|
CComVariant varServerNumber;
|
|
|
|
// Read ADsWebPath and ServerNumber to form: IIS://localhost/W3SVC/1
|
|
hr = m_pProvHelper->GetRollbackData(IIS_ROLL_ADSPATH, &varWebADsPath);
|
|
if (SUCCEEDED(hr) ) hr = m_pProvHelper->GetRollbackData(IIS_ROLL_SERVERNUMBER, &varServerNumber);
|
|
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
bServerNumber = varServerNumber.bstrVal;
|
|
bWebADsPath = varWebADsPath.bstrVal;
|
|
|
|
|
|
if ( bServerNumber.Length() > 0 )
|
|
{
|
|
bstrConfigPath = bWebADsPath.Copy();
|
|
bstrConfigPath.Append(L"/");
|
|
bstrConfigPath.AppendBSTR(bServerNumber.m_str);
|
|
|
|
|
|
// Step 1: ShutDown Server
|
|
hr = IIsServerAction(bstrConfigPath,stop);
|
|
|
|
// Step 2: Delete the server
|
|
if (SUCCEEDED(hr) ) hr = DeleteIIs50Site(IIS_IISWEBSERVER,bWebADsPath,bServerNumber);
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_INVALID_INDEX;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_INVALID_INDEX;
|
|
}
|
|
|
|
|
|
// Log failure.
|
|
IIsScoLogFailure();
|
|
|
|
TRACE_EXIT(L"CIISSCO50::CreateWebSiteRollback");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::DeleteWebSite_Execute
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters an action
|
|
// tag: DeleteWebSite. Code deletes a IIS 5 web site
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::DeleteWebSite_Execute( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::DeleteWebSite");
|
|
|
|
CComBSTR bWebADsPath; // adsPath: IIS://server/W3SVC
|
|
CComBSTR bstrServer; // Server name; localhost if black
|
|
CComBSTR bServerNumber; // WebSite number: 3
|
|
CComBSTR bstrConfigPath; // Full configuartion path: IIS://localhost/W3SVC/3
|
|
CComPtr<IXMLDOMNode> pNode; // xml node <website>
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Get node in format: <executeData><Website number=''><Root />...
|
|
CComBSTR bstrDebug;
|
|
//hr = pXMLNode->get_xml(&bstrDebug);
|
|
|
|
hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
|
|
hr = pNode->get_xml(&bstrDebug);
|
|
ATLTRACE(_T("\t>>> xml = : %ls\n"), bstrDebug.m_str);
|
|
|
|
// Get properties from XML
|
|
hr = GetInputAttr(pNode, L"./Website", L"number", bServerNumber);
|
|
hr = GetInputParam(pNode,L"./Website/Server", bstrServer);
|
|
|
|
// Create a IIS metabase path. ex. IIS://localhost/W3SVC
|
|
bWebADsPath = IIS_PREFIX;
|
|
if ( bstrServer.Length() == 0 )
|
|
bstrServer = IIS_LOCALHOST;
|
|
|
|
bWebADsPath.AppendBSTR(bstrServer);
|
|
bWebADsPath.Append(IIS_W3SVC);
|
|
|
|
// CreateFull configuartion path: IIS://localhost/W3SVC/3
|
|
bstrConfigPath = bWebADsPath.Copy();
|
|
bstrConfigPath.Append(L"/");
|
|
bstrConfigPath.AppendBSTR(bServerNumber.m_str);
|
|
|
|
if ( bServerNumber.Length() > 0 )
|
|
{
|
|
|
|
// Step 1: ShutDown Server
|
|
hr = IIsServerAction(bstrConfigPath,stop);
|
|
IIsScoLogFailure();
|
|
|
|
// Step 2: Delete the server
|
|
if (SUCCEEDED(hr) ) hr = DeleteIIs50Site(IIS_IISWEBSERVER,bWebADsPath,bServerNumber);
|
|
IIsScoLogFailure();
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
|
|
// DeleteSite successfully. Set Rollback data to be whole xml node
|
|
// incase another step in SCO fails a RollBack is required.
|
|
CComBSTR webXML;
|
|
hr = pNode->get_xml(&webXML);
|
|
|
|
// convert BSTR to Variant and save in RollbackData
|
|
CComVariant varData(webXML);
|
|
hr = m_pProvHelper->SetRollbackData(IIS_ROLL_XNODE, varData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_INVALID_INDEX;
|
|
}
|
|
|
|
if ( FAILED(hr) )
|
|
IIsScoLogFailure();
|
|
|
|
TRACE_EXIT(L"CIISSCO50::DeleteWebSite");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::DeleteWebSite_Rollback
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters a failure during
|
|
// 'DeleteWebSite'. The Rollback recreates the WebSite if it can.
|
|
// MAPS returns data in the format: <executeData><Website number=''>...
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::DeleteWebSite_Rollback( IXMLDOMNode *pXMLNode )
|
|
{
|
|
//hr = m_pProvHelper->GetRollbackData(L"key", &varData );
|
|
|
|
TRACE_ENTER(L"CIISSCO50::DeleteWebSiteRollback");
|
|
|
|
CComBSTR bWebADsPath; // adsPath: IIS://server/W3SVC
|
|
CComBSTR bstrRoot; // root directory path: c:/inetpub
|
|
CComBSTR bstrServer; // Server name; localhost if black
|
|
CComBSTR bstrSiteName; // site name; www.mysite.com
|
|
CComBSTR bstrHost; // Web Hostname
|
|
CComBSTR bstrPort; // Web port number
|
|
CComBSTR bstrIP; // Web IP address
|
|
CComBSTR bstrSBindings; // Server bindings: IP:Post:HostName
|
|
CComBSTR bServerNumber; // WebSite number: 3
|
|
//CComBSTR bFilePermissions; // File permissions: domain\user:F
|
|
CComBSTR bstrStart; // Start site when done? TRUE/FALSE
|
|
CComBSTR bConfigPath; // Initial <ConfigPath> value: /W3SVC/3
|
|
CComBSTR bstrConfigPath; // Created sites ADsPath: /W3SVC/3
|
|
|
|
CComVariant xmlString; // Variant string returned by MAPS
|
|
|
|
CComPtr<IXMLDOMDocument> pDoc; // xml document
|
|
CComPtr<IXMLDOMNodeList> pNodeList; // xml node list <website>
|
|
CComPtr<IXMLDOMNode> pNode; // xml node <website>
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Get RollBack data. Will bein form: <executeData><Website number=''>...
|
|
hr = m_pProvHelper->GetRollbackData(IIS_ROLL_XNODE, &xmlString);
|
|
|
|
// load xml string into XML Dom
|
|
if ( xmlString.bstrVal != NULL )
|
|
{
|
|
hr = CoCreateInstance(
|
|
__uuidof(DOMDocument),
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
__uuidof(IXMLDOMDocument),
|
|
(LPVOID*)&pDoc);
|
|
|
|
VARIANT_BOOL bSuccess = VARIANT_FALSE;
|
|
hr = pDoc->loadXML(xmlString.bstrVal, &bSuccess);
|
|
|
|
if ( SUCCEEDED(hr) && bSuccess != VARIANT_FALSE)
|
|
{
|
|
// Check that there is a <Website> tag
|
|
hr = pDoc->getElementsByTagName(L"Website",&pNodeList);
|
|
long numChild = 0;
|
|
if (SUCCEEDED(hr)) hr = pNodeList->get_length(&numChild);
|
|
|
|
if ( numChild > 0 )
|
|
{
|
|
// Get the next node which is <Website number=''>
|
|
hr = pNodeList->nextNode(&pNode);
|
|
|
|
|
|
// Get Server number from attribute map <Website number=2">
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
hr = GetInputAttr(pNode, L"", L"number", bServerNumber);
|
|
if ( !IsPositiveInteger(bServerNumber) )
|
|
{
|
|
//hr = GetElement(pNode, L"ConfigPath", bConfigPath);
|
|
hr = ParseBSTR(bConfigPath,L'/', 2, 99, bServerNumber);
|
|
}
|
|
|
|
// Check Server number is valid
|
|
if ( !IsPositiveInteger(bServerNumber) )
|
|
{
|
|
hr = E_SCO_IIS_INVALID_INDEX;
|
|
IIsScoLogFailure();
|
|
}
|
|
}
|
|
|
|
// Get properties from XML
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./Root", bstrRoot);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./Server", bstrServer);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./SiteName", bstrSiteName);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./HostName", bstrHost);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./PortNumber", bstrPort);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./IPAddress", bstrIP);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./StartOnCreate", bstrStart);
|
|
//if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./FilePermissions", bFilePermissions);
|
|
|
|
// Create a IIS metabase path. ex. IIS://localhost/W3SVC
|
|
bWebADsPath = IIS_PREFIX;
|
|
if ( bstrServer.Length() == 0 )
|
|
bstrServer = IIS_LOCALHOST;
|
|
|
|
bWebADsPath.AppendBSTR(bstrServer);
|
|
bWebADsPath.Append(IIS_W3SVC);
|
|
|
|
// Step .5: If port number missing, set to default (ie, 80)
|
|
if ( bstrPort.Length() == 0 )
|
|
bstrPort = IIS_DEFAULT_WEB_PORT;
|
|
|
|
if ( IsPositiveInteger(bstrPort) )
|
|
{
|
|
|
|
// Step 1: Create the ServerBinding string then check bindings to make sure
|
|
// there is not a duplicate server
|
|
CreateBindingString(bstrIP, bstrPort, bstrHost, bstrSBindings);
|
|
|
|
if (SUCCEEDED(hr) ) hr = CheckBindings(bWebADsPath, bstrSBindings);
|
|
IIsScoLogFailure();
|
|
|
|
// Step 2: Recreate Web Server
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
|
|
// Step 3: Create the Web Site on given path, ServerNumber.
|
|
if (SUCCEEDED(hr)) hr = CreateIIs50Site(IIS_IISWEBSERVER,bWebADsPath, bServerNumber, bstrConfigPath);
|
|
IIsScoLogFailure();
|
|
|
|
// Step 4: Create a Virtual directory on new IIsWebServer configPath
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrVDirAdsPath;
|
|
hr = CreateIIs50VDir(IIS_IISWEBVIRTUALDIR, bstrConfigPath,L"ROOT", L"Default Application", bstrRoot, bstrVDirAdsPath);
|
|
IIsScoLogFailure();
|
|
|
|
// Step 5: set each property; ie, server bindings
|
|
// Bind to ADs object
|
|
CComPtr<IADs> pADs;
|
|
if (SUCCEEDED(hr)) hr = ADsGetObject(bstrConfigPath, IID_IADs, (void**) &pADs );
|
|
if ( FAILED(hr) )
|
|
{
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
}
|
|
|
|
// Set "ServerComment" property
|
|
if (SUCCEEDED(hr) && bstrSiteName.Length() > 0 )
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerComment", bstrSiteName);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) hr = SetMetaPropertyValue(pADs, L"ServerBindings", bstrSBindings);
|
|
IIsScoLogFailure();
|
|
|
|
|
|
// Step 6: Start Server if required IIS_FALSE
|
|
bstrStart.ToUpper();
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
if ( !StringCompare(bstrStart, IIS_FALSE) )
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_TRUE);
|
|
IIsScoLogFailure();
|
|
|
|
hr = IIsServerAction(bstrConfigPath,start);
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_FALSE);
|
|
IIsScoLogFailure();
|
|
|
|
}
|
|
}
|
|
|
|
// If there is a failure, 'IIsScoLogFailure' macro will log error
|
|
if ( FAILED(hr) )
|
|
{
|
|
// First delete any webseites that were created in the method. Do this here because a RollBack
|
|
// will only get called on a completed previous <step>, not a failed step.
|
|
DeleteIIs50Site(IIS_IISWEBSERVER,bWebADsPath,bServerNumber);
|
|
|
|
}
|
|
} // if Step 4
|
|
|
|
} // if Step 3
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_PORTNUMBER_NOT_VALID;
|
|
IIsScoLogFailure();
|
|
} // portnumber positive
|
|
|
|
} // if hasChild
|
|
} // if isSuccessfull
|
|
}
|
|
|
|
// Log failure.
|
|
if ( FAILED(hr))
|
|
IIsScoLogFailure();
|
|
|
|
|
|
TRACE_EXIT(L"CIISSco50Obj::DeleteWebSiteRollback");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::CreateFTPSite_Execute
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters an action
|
|
// tag: CreateFTPSite. Code creates a IIS 5 ftp site
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::CreateFTPSite_Execute( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::CreateFTPSite");
|
|
HRESULT hr = S_OK;
|
|
|
|
CComBSTR bFTPADsPath; // adsPath: IIS://server/MSFTPSVC
|
|
CComBSTR bstrRoot; // root directory path: c:/inetpub
|
|
CComBSTR bstrServer; // Server name; localhost if black
|
|
CComBSTR bstrSiteName; // site name; www.mysite.com
|
|
CComBSTR bstrPort; // Web port number
|
|
CComBSTR bstrIP; // Web IP address
|
|
CComBSTR bstrSBindings; // Server bindings: IP:Post:HostName
|
|
CComBSTR bServerNumber; // WebSite number: 3
|
|
//CComBSTR bFilePermissions; // File permissions: domain\user:F
|
|
CComBSTR bstrStart; // Start site when done? TRUE/FALSE
|
|
CComBSTR bstrConfigPath; // Created sites ADsPath: /MSFTPSVC/3
|
|
CComPtr<IXMLDOMNode> pNode; // xml node <website>
|
|
|
|
// Get node in format: <executeData><FTPsite number=''><Root />...
|
|
hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
|
|
|
|
|
|
// Get properties from XML
|
|
hr = GetInputAttr(pNode, L"./FTPsite", L"number", bServerNumber);
|
|
hr = GetInputParam(pNode,L"./FTPsite/Root", bstrRoot);
|
|
hr = GetInputParam(pNode,L"./FTPsite/Server", bstrServer);
|
|
hr = GetInputParam(pNode,L"./FTPsite/SiteName", bstrSiteName);
|
|
hr = GetInputParam(pNode,L"./FTPsite/PortNumber", bstrPort);
|
|
hr = GetInputParam(pNode,L"./FTPsite/IPAddress", bstrIP);
|
|
hr = GetInputParam(pNode,L"./FTPsite/StartOnCreate", bstrStart);
|
|
//hr = GetInputParam(pNode,L"./FTPsite/FilePermissions", bFilePermissions);
|
|
|
|
// Create a IIS metabase path. ex. IIS://localhost/MSFTPSVC
|
|
bFTPADsPath = IIS_PREFIX;
|
|
if ( bstrServer.Length() == 0 )
|
|
bstrServer = IIS_LOCALHOST;
|
|
|
|
bFTPADsPath.AppendBSTR(bstrServer);
|
|
bFTPADsPath.Append(IIS_MSFTPSVC);
|
|
|
|
// Step .5: If port number missing, set to default (ie, 21)
|
|
if ( bstrPort.Length() == 0 )
|
|
bstrPort = IIS_DEFAULT_FTP_PORT;
|
|
|
|
if ( IsPositiveInteger(bstrPort) )
|
|
{
|
|
|
|
// Step 1: Create the ServerBinding string to make sure not a duplicate server
|
|
hr = CreateBindingString(bstrIP, bstrPort, L"", bstrSBindings);
|
|
|
|
hr = CheckBindings(bFTPADsPath, bstrSBindings);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
|
|
// Step 2: Get Next available Server Index
|
|
if ( bServerNumber.Length() == 0 )
|
|
hr = GetNextIndex(bFTPADsPath,bServerNumber);
|
|
|
|
|
|
// Step 3: Create the Web Site on given path, ServerNumber.
|
|
if (SUCCEEDED(hr)) hr = CreateIIs50Site(IIS_IISFTPSERVER,bFTPADsPath, bServerNumber, bstrConfigPath);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
// Step 4: Create a Virtual directory on new IIsWebServer configPath
|
|
CComBSTR bstrVDirAdsPath;
|
|
hr = CreateIIs50VDir(IIS_FTPVDIR,bstrConfigPath,L"ROOT", L"Default Application", bstrRoot, bstrVDirAdsPath);
|
|
IIsScoLogFailure();
|
|
|
|
// Step 5: set each property
|
|
CComPtr<IADs> pADs;
|
|
if (SUCCEEDED(hr)) hr = ADsGetObject(bstrConfigPath, IID_IADs, (void**) &pADs );
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
// Set "ServerComment" property
|
|
if (bstrSiteName.Length() > 0 )
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerComment", bstrSiteName);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Set "ServerBindings"
|
|
if (SUCCEEDED(hr)) hr = SetMetaPropertyValue(pADs, L"ServerBindings", bstrSBindings);
|
|
IIsScoLogFailure();
|
|
|
|
|
|
// Step 6: Start Server if required IIS_FALSE
|
|
bstrStart.ToUpper();
|
|
if ( SUCCEEDED(hr) && !StringCompare(bstrStart, IIS_FALSE) )
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_TRUE);
|
|
IIsScoLogFailure();
|
|
|
|
hr = IIsServerAction(bstrConfigPath,start);
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_FALSE);
|
|
IIsScoLogFailure();
|
|
|
|
}
|
|
|
|
|
|
// Step 7: write ConfigPath to output.
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
CComBSTR bstrXML1 = IIS_MSFTPSVC;
|
|
bstrXML1.Append(L"/");
|
|
bstrXML1.AppendBSTR(bServerNumber.m_str);
|
|
|
|
// Helper function to write to DOM
|
|
hr = PutElement(pNode, L"./FTPsite/ConfigPath", bstrXML1.m_str);
|
|
IIsScoLogFailure();
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
IIsScoLogFailure();
|
|
|
|
} // end step 4
|
|
|
|
// If something failed between steps 5-7, delete FTP site created in step 3
|
|
if ( FAILED(hr) )
|
|
{
|
|
// First delete any ftp sites that were created in the method. Do this here because a RollBack
|
|
// will only get called on a completed previous <step>, not a failed step.
|
|
DeleteIIs50Site(IIS_IISFTPSERVER,bFTPADsPath,bServerNumber);
|
|
}
|
|
|
|
} // end if L"CreateFTPSite: Could not create FTP site."
|
|
|
|
} // end if FTP ServerBindings already existed."
|
|
}
|
|
else
|
|
{
|
|
// L"CreateFTPSite: Port number must be positive value."
|
|
hr = E_SCO_IIS_PORTNUMBER_NOT_VALID;
|
|
}
|
|
|
|
|
|
// If there is a failure.
|
|
if ( FAILED(hr) )
|
|
{
|
|
// L"CreateFTPSite failed."
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
// FTP Site successfully created. Set Rollback data incase another step fails
|
|
CComVariant varData1(bFTPADsPath);
|
|
CComVariant varData2(bServerNumber);
|
|
hr = m_pProvHelper->SetRollbackData(IIS_ROLL_ADSPATH, varData1);
|
|
hr = m_pProvHelper->SetRollbackData(IIS_ROLL_SERVERNUMBER, varData2);
|
|
}
|
|
|
|
|
|
TRACE_EXIT(L"CIISSCO50::CreateFTPSite");
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::CreateFTPSite_Rollback
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters a failure during
|
|
// 'CreateFTPSite'. The Rollback deletes the ftp if it can.
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::CreateFTPSite_Rollback( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::CreateFTPSiteRollback");
|
|
HRESULT hr = S_OK;
|
|
CComBSTR bFTPADsPath; // AdsPath: IIS://server/MSFTPSVC
|
|
CComBSTR bServerNumber; // Web server number
|
|
CComBSTR bstrConfigPath; // Complete ADsPath to check: IIS://localhost/MSFTPSVC/1
|
|
|
|
CComVariant varFTPADsPath;
|
|
CComVariant varServerNumber;
|
|
|
|
// Read ADsFTPPath and ServerNumber to form: IIS://localhost/MSFTPSVC/1
|
|
hr = m_pProvHelper->GetRollbackData(IIS_ROLL_ADSPATH, &varFTPADsPath);
|
|
if (SUCCEEDED(hr) ) hr = m_pProvHelper->GetRollbackData(IIS_ROLL_SERVERNUMBER, &varServerNumber);
|
|
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
bServerNumber = varServerNumber.bstrVal;
|
|
bFTPADsPath = varFTPADsPath.bstrVal;
|
|
|
|
bstrConfigPath = bFTPADsPath.Copy();
|
|
bstrConfigPath.Append(L"/");
|
|
bstrConfigPath.AppendBSTR(bServerNumber.m_str);
|
|
}
|
|
|
|
|
|
// Step 1: ShutDown Server
|
|
if (SUCCEEDED(hr)) hr = IIsServerAction(bstrConfigPath,stop);
|
|
|
|
// Only a warning if can't stop/start server given correct server path
|
|
|
|
// Step 2: Delete the server
|
|
hr = DeleteIIs50Site(IIS_IISFTPSERVER,bFTPADsPath,bServerNumber);
|
|
IIsScoLogFailure();
|
|
|
|
|
|
TRACE_EXIT(L"CIISSCO50::CreateFTPSiteRollback");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::DeleteFTPSite_Execute
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters an action
|
|
// tag: DeleteFTPSite. Code deletes a IIS 5 ftp site
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::DeleteFTPSite_Execute( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::DeleteFTPSite");
|
|
|
|
CComBSTR bFTPADsPath; // adsPath: IIS://server/MSFTPSVC
|
|
CComBSTR bstrServer; // Server name; localhost if blank
|
|
CComBSTR bServerNumber; // WebSite number: 3
|
|
CComBSTR bstrConfigPath; // Full configuartion path: IIS://localhost/MSFTPSVC/3
|
|
CComPtr<IXMLDOMNode> pNode; // xml node <website>
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Get node in format: <executeData><FTPsite number=''><Root />...
|
|
hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
|
|
|
|
|
|
// Get properties from XML
|
|
hr = GetInputAttr(pNode, L"./FTPsite", L"number", bServerNumber);
|
|
hr = GetInputParam(pNode,L"./FTPsite/Server", bstrServer);
|
|
|
|
// Step .5: Make sure Server Number is a positive integer
|
|
if ( IsPositiveInteger(bServerNumber) )
|
|
{
|
|
|
|
|
|
// Create a IIS metabase path. ex. IIS://localhost/MSFTPSVC
|
|
bFTPADsPath = IIS_PREFIX;
|
|
if ( bstrServer.Length() == 0 )
|
|
bstrServer = IIS_LOCALHOST;
|
|
|
|
bFTPADsPath.AppendBSTR(bstrServer);
|
|
bFTPADsPath.Append(IIS_MSFTPSVC);
|
|
|
|
// Create metabase path to object: IIS://localhost/MSFTPSVC/1
|
|
bstrConfigPath = bFTPADsPath.Copy();
|
|
bstrConfigPath.Append(L"/");
|
|
bstrConfigPath.AppendBSTR(bServerNumber.m_str);
|
|
|
|
// Step 1: ShutDown Server
|
|
hr = IIsServerAction(bstrConfigPath,stop);
|
|
|
|
// Only a warning if can't stop/start server
|
|
|
|
// Step 2: Delete the server
|
|
hr = DeleteIIs50Site(IIS_IISFTPSERVER,bFTPADsPath,bServerNumber);
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
// L"DeleteFTPSite: Invalid Server number."
|
|
hr = E_SCO_IIS_INVALID_INDEX;
|
|
IIsScoLogFailure();
|
|
|
|
}
|
|
|
|
// If there is a failure
|
|
if ( FAILED(hr) )
|
|
{
|
|
// L"DeleteFTPSite failed."
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
// DeleteSite successfully. Set Rollback data to be whole xml node
|
|
// incase another step in SCO fails a RollBack is required.
|
|
CComBSTR webXML;
|
|
hr = pNode->get_xml(&webXML);
|
|
|
|
// convert BSTR to Variant and save in RollbackData
|
|
CComVariant varData(webXML);
|
|
hr = m_pProvHelper->SetRollbackData(IIS_ROLL_XNODE, varData);
|
|
}
|
|
|
|
TRACE_EXIT(L"CIISSCO50::DeleteFTPSite");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::DeleteFTPSite_Rollback
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters a failure during
|
|
// 'DeleteFTPSite'. The Rollback recreates the ftp Site if it can.
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::DeleteFTPSite_Rollback( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::DeleteFTPSiteRollback");
|
|
|
|
CComBSTR bFTPADsPath; // adsPath: IIS://server/MSFTPSVC
|
|
CComBSTR bstrRoot; // root directory path: c:/inetpub
|
|
CComBSTR bstrServer; // Server name; localhost if black
|
|
CComBSTR bstrSiteName; // site name; www.mysite.com
|
|
CComBSTR bstrPort; // Web port number
|
|
CComBSTR bstrIP; // Web IP address
|
|
CComBSTR bstrSBindings; // Server bindings: IP:Post:HostName
|
|
CComBSTR bServerNumber; // WebSite number: 3
|
|
//CComBSTR bFilePermissions; // File permissions: domain\user:F
|
|
CComBSTR bstrStart; // Start site when done? TRUE/FALSE
|
|
CComBSTR bConfigPath; // Initial <ConfigPath> value: /MSFTPSVC/3
|
|
CComBSTR bstrConfigPath; // Created sites ADsPath: /MSFTPSVC/3
|
|
|
|
CComVariant xmlString;
|
|
|
|
CComPtr<IXMLDOMDocument> pDoc; // xml document
|
|
CComPtr<IXMLDOMNodeList> pNodeList; // xml node list <website>
|
|
CComPtr<IXMLDOMNode> pNode; // xml node <website>
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Get RollBack data. Will bein form: <executeData><Website number=''>...
|
|
hr = m_pProvHelper->GetRollbackData(IIS_ROLL_XNODE, &xmlString);
|
|
|
|
// load xml string into XML Dom
|
|
if ( xmlString.bstrVal != NULL )
|
|
{
|
|
|
|
hr = CoCreateInstance(
|
|
__uuidof(DOMDocument),
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
__uuidof(IXMLDOMDocument),
|
|
(LPVOID*)&pDoc);
|
|
|
|
VARIANT_BOOL bSuccess = VARIANT_FALSE;
|
|
if ( SUCCEEDED(hr) ) hr = pDoc->loadXML(xmlString.bstrVal, &bSuccess);
|
|
|
|
if ( SUCCEEDED(hr) && bSuccess != VARIANT_FALSE)
|
|
{
|
|
// Check that there is a <FTPSite number= > tag
|
|
hr = pDoc->getElementsByTagName(L"FTPsite",&pNodeList);
|
|
long numChild = 0;
|
|
if (SUCCEEDED(hr)) hr = pNodeList->get_length(&numChild);
|
|
|
|
if ( numChild > 0 )
|
|
{
|
|
hr = pNodeList->nextNode(&pNode);
|
|
|
|
// Get Server number from attribute map <FTPSite number=2">
|
|
if (SUCCEEDED(hr) ) hr = GetInputAttr(pNode, L"", L"number", bServerNumber);
|
|
|
|
// Check Server number is valid
|
|
if ( !IsPositiveInteger(bServerNumber) )
|
|
{
|
|
// L"DeleteFTPSiteRollback: FTP Server Number missing."
|
|
hr = E_SCO_IIS_INVALID_INDEX;
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Get properties from XML
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./Root", bstrRoot);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./Server", bstrServer);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./SiteName", bstrSiteName);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./PortNumber", bstrPort);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./IPAddress", bstrIP);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./StartOnCreate", bstrStart);
|
|
//if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./FilePermissions", bFilePermissions);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./ConfigPath", bConfigPath);
|
|
|
|
// Create a IIS metabase path. ex. IIS://localhost/W3SVC
|
|
bFTPADsPath = IIS_PREFIX;
|
|
if ( bstrServer.Length() == 0 )
|
|
bstrServer = IIS_LOCALHOST;
|
|
|
|
bFTPADsPath.AppendBSTR(bstrServer);
|
|
bFTPADsPath.Append(IIS_MSFTPSVC);
|
|
|
|
// Step .5: If port number missing, set to default (ie, 21)
|
|
if ( bstrPort.Length() == 0 )
|
|
bstrPort = IIS_DEFAULT_FTP_PORT;
|
|
|
|
if ( IsPositiveInteger(bstrPort) )
|
|
{
|
|
|
|
|
|
// Step 1: Create the ServerBinding string to make sure not a duplicate server
|
|
hr = CreateBindingString(bstrIP, bstrPort, L"", bstrSBindings);
|
|
|
|
if (SUCCEEDED(hr)) hr = CheckBindings(bFTPADsPath, bstrSBindings);
|
|
IIsScoLogFailure();
|
|
|
|
|
|
// Step 2 Recreate FTP Server
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
|
|
// Step 3: Create the Web Site on given path, ServerNumber.
|
|
hr = CreateIIs50Site(IIS_IISFTPSERVER,bFTPADsPath, bServerNumber, bstrConfigPath);
|
|
IIsScoLogFailure();
|
|
|
|
// Step 4: Create a Virtual directory on new IIsFtpVirtualDir configPath
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
CComBSTR bstrVDirAdsPath;
|
|
hr = CreateIIs50VDir(IIS_FTPVDIR,bstrConfigPath,L"ROOT", L"Default Application", bstrRoot, bstrVDirAdsPath);
|
|
IIsScoLogFailure();
|
|
|
|
// Step 5 - set properties
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
|
|
CComPtr<IADs> pADs;
|
|
hr = ADsGetObject(bstrConfigPath, IID_IADs, (void**) &pADs );
|
|
if ( FAILED(hr) )
|
|
{
|
|
// L"DeleteFTPSiteRollback: Create FTP adsi object failed."
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
// Set "ServerComment" property
|
|
if (bstrSiteName.Length() > 0 )
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerComment", bstrSiteName);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Set "ServerBindings"
|
|
if (SUCCEEDED(hr)) hr = SetMetaPropertyValue(pADs, L"ServerBindings", bstrSBindings);
|
|
IIsScoLogFailure();
|
|
|
|
|
|
// Step 6: Start Server if required IIS_FALSE
|
|
bstrStart.ToUpper();
|
|
if ( SUCCEEDED(hr) && !StringCompare(bstrStart, IIS_FALSE) )
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_TRUE);
|
|
IIsScoLogFailure();
|
|
|
|
hr = IIsServerAction(bstrConfigPath,start);
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
if (SUCCEEDED(hr)) hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_FALSE);
|
|
IIsScoLogFailure();
|
|
|
|
}
|
|
|
|
} // end if Step 5
|
|
}
|
|
|
|
// If failure, delete the FTP site
|
|
if ( FAILED(hr))
|
|
{
|
|
DeleteIIs50Site(IIS_IISFTPSERVER,bFTPADsPath,bServerNumber);
|
|
}
|
|
} // end step 4
|
|
|
|
|
|
} // end if Step 2
|
|
}
|
|
else
|
|
{
|
|
// L"DeleteWebSiteRollback: Port number not a positive integer."
|
|
hr = E_SCO_IIS_PORTNUMBER_NOT_VALID;
|
|
|
|
} // step .5 portnumber positive
|
|
|
|
} // if numChild > 0
|
|
|
|
} // if isSuccessfull
|
|
}
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
// DeleteFTPSiteRollback failed."
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
|
|
TRACE_EXIT(L"CIISSCO50::DeleteFTPSiteRollback");
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::CreateVDir_Execute
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters an action
|
|
// tag: CreateVDir. Code creates a IIS 5 Virtual Directory
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::CreateVDir_Execute( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::CreateVDir");
|
|
|
|
CComBSTR bstrConfigPath; // adsPath: IIS://server/W3SVC/1/ROOT/MyDir
|
|
CComBSTR bServerNumber; // Server number
|
|
CComBSTR bstrServer; // Server name; localhost if blank
|
|
//CComBSTR bFilePermissions; // File permissions: domain\user:F
|
|
CComBSTR bstrDirPath; // root directory path: c:/inetpub
|
|
CComBSTR bstrVDirName; // Virtual Directory name; MyDir
|
|
CComBSTR bstrFriendlyName; // Display name or AppFriendlyName
|
|
CComBSTR bstrAppCreate; // AppCreate flag -- TRUE/FALSE
|
|
CComBSTR bstrIsoLevel; // AppIsolationLevel
|
|
CComBSTR bstrAccessRead; // AccessFalgs - AccessRead = TRUE/FALSE
|
|
CComBSTR bstrAccessScript; // AccessFalgs - AccessScript = TRUE/FALSE
|
|
CComBSTR bstrAccessWrite; // AccessFalgs - AccessWrite = TRUE/FALSE
|
|
CComBSTR bstrAccessExecute; // AccessFalgs - AccessExecute = TRUE/FALSE
|
|
|
|
CComPtr<IXMLDOMNode> pNode; // xml node. will be <executeData><VirtualDirectory>
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Get node in format: <executeData><VirtualDirectory number=''><Root />...
|
|
hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
|
|
|
|
// Get properties from XML
|
|
hr = GetInputAttr(pNode,L"./VirtualDirectory", L"number", bServerNumber);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/Server", bstrServer);
|
|
//hr = GetInputParam(pNode,L"./VirtualDirectory/FilePermissions", bFilePermissions);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/Path", bstrDirPath);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/VDirName", bstrVDirName);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/DisplayName", bstrFriendlyName);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/AppCreate", bstrAppCreate);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/AppIsolationLevel", bstrIsoLevel);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/AccessRead", bstrAccessRead);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/AccessScript", bstrAccessScript);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/AccessWrite", bstrAccessWrite);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/AccessExecute", bstrAccessExecute);
|
|
|
|
|
|
// Step 1: Get Server number where VDir will be created
|
|
if ( !IsPositiveInteger(bServerNumber))
|
|
{
|
|
// "CreateVDir: Server number missing."
|
|
hr = E_SCO_IIS_INVALID_INDEX;
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
|
|
|
|
// Step 2: Construct the Metabase path that VDir will be created on.
|
|
// ex) IIS://localhost/W3SVC/1/ROOT
|
|
bstrConfigPath = IIS_PREFIX;
|
|
|
|
// append server name, W3SVC and server number
|
|
if ( bstrServer.Length() == 0 )
|
|
bstrServer = IIS_LOCALHOST;
|
|
|
|
bstrConfigPath.AppendBSTR(bstrServer);
|
|
bstrConfigPath.Append(IIS_W3SVC);
|
|
bstrConfigPath.Append(L"/");
|
|
bstrConfigPath.AppendBSTR(bServerNumber);
|
|
|
|
// if there is a VDir name, then it must be under 'ROOT'
|
|
if ( bstrVDirName.Length() == 0 )
|
|
{
|
|
bstrVDirName = IIS_VROOT;
|
|
}
|
|
else
|
|
{
|
|
bstrConfigPath.Append(L"/");
|
|
bstrConfigPath.Append(IIS_VROOT);
|
|
}
|
|
|
|
//Step 2: Get the AppFriendlyName
|
|
if ( bstrFriendlyName.Length() == 0 )
|
|
bstrFriendlyName = IIS_VDEFAULT_APP;
|
|
|
|
// Step 3: Create a Virtual directory on new IIsWebServer configPath
|
|
CComBSTR bstrVDirAdsPath;
|
|
hr = CreateIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath,bstrVDirName, bstrFriendlyName, bstrDirPath, bstrVDirAdsPath);
|
|
IIsScoLogFailure();
|
|
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
// Step 4: set each of the properties
|
|
// Set the server bindings
|
|
CComPtr<IADs> pADs;
|
|
if (SUCCEEDED(hr)) hr = ADsGetObject( bstrVDirAdsPath,IID_IADs, (void **)&pADs);
|
|
if ( FAILED(hr))
|
|
{
|
|
// "CreateVDir: Failed to create IADs object for VDir path."
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Bug# 453928 -- Default AppIsolationLevel is 2
|
|
if ( !IsPositiveInteger(bstrIsoLevel))
|
|
bstrIsoLevel = IIS_DEFAULT_APPISOLATED;
|
|
|
|
// Set AppIsolationLevel -- 'AppIsolated'
|
|
if (SUCCEEDED(hr)) hr = SetVDirProperty(pADs, L"AppIsolated",bstrIsoLevel);
|
|
IIsScoLogFailure();
|
|
|
|
// Set AccessFlags'
|
|
if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
|
|
{
|
|
hr = SetVDirProperty(pADs, L"AccessRead",bstrAccessRead);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
|
|
{
|
|
hr = SetVDirProperty(pADs, L"AccessScript",bstrAccessScript);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
|
|
{
|
|
hr = SetVDirProperty(pADs, L"AccessWrite",bstrAccessWrite);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
|
|
{
|
|
hr = SetVDirProperty(pADs, L"AccessExecute",bstrAccessExecute);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Step 5: If AppCreate is FALSE, then remove the following properties.
|
|
// Bug# 453923
|
|
bstrAppCreate.ToUpper();
|
|
if ( SUCCEEDED(hr) && StringCompare(bstrAppCreate, IIS_FALSE) )
|
|
{
|
|
hr = DeleteMetaPropertyValue(pADs, L"AppIsolated");
|
|
|
|
if SUCCEEDED(hr) hr = DeleteMetaPropertyValue(pADs, L"AppRoot");
|
|
|
|
if SUCCEEDED(hr) hr = DeleteMetaPropertyValue(pADs, L"AppFriendlyName");
|
|
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
|
|
|
|
|
|
// If there is a failure.
|
|
if ( FAILED(hr) )
|
|
{
|
|
// First delete any virtual directories that were created in the method. Do this here because a RollBack
|
|
// will only get called on a completed previous <step>, not a failed step.
|
|
DeleteIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath, bstrVDirName);
|
|
}
|
|
else
|
|
{
|
|
CComBSTR bstrXML1;
|
|
// ParseBSTR
|
|
// Input: IIS://MyServer/W3SVC/1/ROOT/MyDir
|
|
// Output: /W3SVC/1/ROOT/MyDir
|
|
hr = ParseBSTR(bstrVDirAdsPath,bstrServer, 1, 99,bstrXML1);
|
|
|
|
// Matches line: <output type="WebSiteOutput" root="VirtualDirectory">
|
|
hr = PutElement(pNode, L"./VirtualDirectory/ConfigPath", bstrXML1.m_str);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If there is a failure.
|
|
if ( FAILED(hr) )
|
|
{
|
|
// CreateVDir failed.
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
// WebSite successfully created. Set Rollback data incase another step fails
|
|
// a a ROllBack is initiated.
|
|
CComVariant varData1(bstrConfigPath);
|
|
CComVariant varData2(bstrVDirName);
|
|
hr = m_pProvHelper->SetRollbackData(IIS_ROLL_ADSPATH, varData1);
|
|
hr = m_pProvHelper->SetRollbackData(IIS_ROLL_VNAME, varData2);
|
|
|
|
}
|
|
|
|
|
|
TRACE_EXIT(L"CIISSCO50::CreateVDir");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::CreateVDir_Rollback
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters a failure during
|
|
// 'CreateVDir'. The Rollback deletes the virtual directory if it can.
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::CreateVDir_Rollback( IXMLDOMNode *pXMLNode )
|
|
{
|
|
|
|
TRACE_ENTER(L"CIISSCO50::CreateVDirRollback");
|
|
|
|
HRESULT hr = S_OK;
|
|
CComBSTR bstrVDirName; // Virtual Directory name, ie, MyDir
|
|
CComBSTR bstrConfigPath; // Complete ADsPath to VDir: IIS://localhost/W3SVC/1/ROOT
|
|
|
|
CComVariant varConfigPath;
|
|
CComVariant varVDirName;
|
|
|
|
// Read ADsWebPath and ServerNumber to form: IIS://localhost/W3SVC/1
|
|
hr = m_pProvHelper->GetRollbackData(IIS_ROLL_ADSPATH, &varConfigPath);
|
|
if (SUCCEEDED(hr) ) hr = m_pProvHelper->GetRollbackData(IIS_ROLL_VNAME, &varVDirName);
|
|
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
bstrVDirName = varVDirName.bstrVal;
|
|
bstrConfigPath = varConfigPath.bstrVal;
|
|
|
|
// Step 1: Delete the VDir
|
|
hr = DeleteIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath, bstrVDirName);
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
// "CreateVDirRollback: Failed to retrieve rollback properties."
|
|
hr = E_SCO_IIS_MISSING_FIELD;
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
TRACE_EXIT(L"CIISSCO50::CreateVDirRollback");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::DeleteVDir_Execute
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters an action
|
|
// tag: DeleteVDir. Code deletes a IIS 5 virtual directory
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::DeleteVDir_Execute( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::DeleteVDir");
|
|
|
|
CComBSTR bstrServer; // Server name; localhost if blank
|
|
CComBSTR bstrVDirName; // VDir name
|
|
CComBSTR bServerNumber; // WebSite number: 3
|
|
CComBSTR bstrConfigPath; // Full configuartion path: IIS://server/W3SVC/1/ROOT/MyDir
|
|
CComPtr<IXMLDOMNode> pNode; // xml node <website>
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
CComBSTR bstrDebug;
|
|
hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
|
|
hr = pNode->get_xml(&bstrDebug);
|
|
ATLTRACE(_T("\t>>>DeleteVDir_Execute: xml = : %ls\n"), bstrDebug.m_str);
|
|
|
|
// Get properties from XML
|
|
hr = GetInputAttr(pNode, L"./VirtualDirectory", L"number", bServerNumber);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/Server", bstrServer);
|
|
hr = GetInputParam(pNode,L"./VirtualDirectory/VDirName", bstrVDirName);
|
|
|
|
// Step 1: Get Server number where VDir will be created
|
|
if ( !IsPositiveInteger(bServerNumber) )
|
|
{
|
|
hr = E_SCO_IIS_INVALID_INDEX;
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
// Step 2: Construct the Metabase path that VDir will be created on.
|
|
// ex) IIS://localhost/W3SVC/1/ROOT
|
|
bstrConfigPath = IIS_PREFIX;
|
|
|
|
// append server name, W3SVC and server number
|
|
if ( bstrServer.Length() == 0 )
|
|
bstrServer = IIS_LOCALHOST;
|
|
|
|
bstrConfigPath.AppendBSTR(bstrServer);
|
|
bstrConfigPath.Append(IIS_W3SVC);
|
|
bstrConfigPath.Append("/");
|
|
bstrConfigPath.AppendBSTR(bServerNumber);
|
|
|
|
// if there is a VDir name, then it must be under 'ROOT'
|
|
if ( bstrVDirName.Length() == 0 )
|
|
{
|
|
bstrVDirName = IIS_VROOT;
|
|
}
|
|
else
|
|
{
|
|
bstrConfigPath.Append(L"/");
|
|
bstrConfigPath.Append(IIS_VROOT);
|
|
}
|
|
|
|
|
|
// Step 2: Delete the server
|
|
if (SUCCEEDED(hr)) hr = DeleteIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath, bstrVDirName);
|
|
IIsScoLogFailure();
|
|
|
|
}
|
|
|
|
// If there is a failure
|
|
if ( FAILED(hr) )
|
|
{
|
|
// "DeleteVDir failed."
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
// DeleteSite successfully. Set Rollback data to be whole xml node
|
|
// incase another step in SCO fails a RollBack is required.
|
|
CComBSTR webXML;
|
|
hr = pNode->get_xml(&webXML);
|
|
|
|
// convert BSTR to Variant and save in RollbackData
|
|
CComVariant varData(webXML);
|
|
hr = m_pProvHelper->SetRollbackData(IIS_ROLL_XNODE, varData);
|
|
|
|
}
|
|
|
|
|
|
TRACE_EXIT(L"CIISSCO50::DeleteVDir");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::DeleteVDir_Rollback
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework when is encounters a failure during
|
|
// 'DeleteVDir'. The Rollback recreates the virtual directory if it can.
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::DeleteVDir_Rollback( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::DeleteVDirRollback");
|
|
|
|
CComBSTR bstrConfigPath; // adsPath: IIS://server/W3SVC/1/ROOT/MyDir
|
|
CComBSTR bServerNumber; // Server number
|
|
CComBSTR bstrServer; // Server name; localhost if blank
|
|
//CComBSTR bFilePermissions; // File permissions: domain\user:F
|
|
CComBSTR bstrDirPath; // root directory path: c:/inetpub
|
|
CComBSTR bstrVDirName; // Virtual Directory name; MyDir
|
|
CComBSTR bstrFriendlyName; // Display name or AppFriendlyName
|
|
CComBSTR bstrAppCreate; // AppCreate flag -- TRUE/FALSE
|
|
CComBSTR bstrIsoLevel; // AppIsolationLevel
|
|
CComBSTR bstrAccessRead; // AccessFalgs - AccessRead = TRUE/FALSE
|
|
CComBSTR bstrAccessScript; // AccessFalgs - AccessScript = TRUE/FALSE
|
|
CComBSTR bstrAccessWrite; // AccessFalgs - AccessWrite = TRUE/FALSE
|
|
CComBSTR bstrAccessExecute; // AccessFalgs - AccessExecute = TRUE/FALSE
|
|
|
|
CComVariant xmlString;
|
|
|
|
CComPtr<IXMLDOMDocument> pDoc; // xml document
|
|
CComPtr<IXMLDOMNodeList> pNodeList; // xml node list <website>
|
|
CComPtr<IXMLDOMNode> pNode; // xml node <website>
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Get RollBack data. Will bein form: <executeData><Website number=''>...
|
|
hr = m_pProvHelper->GetRollbackData(IIS_ROLL_XNODE, &xmlString);
|
|
|
|
// load xml string into XML Dom
|
|
if ( xmlString.bstrVal != NULL )
|
|
{
|
|
hr = CoCreateInstance(
|
|
__uuidof(DOMDocument),
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
__uuidof(IXMLDOMDocument),
|
|
(LPVOID*)&pDoc);
|
|
|
|
VARIANT_BOOL bSuccess = VARIANT_FALSE;
|
|
hr = pDoc->loadXML(xmlString.bstrVal, &bSuccess);
|
|
|
|
if ( SUCCEEDED(hr) && bSuccess != VARIANT_FALSE)
|
|
{
|
|
hr = pDoc->getElementsByTagName(XML_NODE_VDIR,&pNodeList);
|
|
long numChild = 0;
|
|
if (SUCCEEDED(hr)) hr = pNodeList->get_length(&numChild);
|
|
|
|
if ( numChild > 0 )
|
|
{
|
|
hr = pNodeList->nextNode(&pNode);
|
|
|
|
// Get Server number from attribute map <VirtualDirectory number=2">
|
|
if (SUCCEEDED(hr) ) hr = GetInputAttr(pNode, L"", L"number", bServerNumber);
|
|
IIsScoLogFailure();
|
|
|
|
// Check Server number is valid
|
|
if ( !IsPositiveInteger(bServerNumber) )
|
|
{
|
|
hr = E_SCO_IIS_INVALID_INDEX;
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Get properties from XML
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/Server", bstrServer);
|
|
//if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/FilePermissions", bFilePermissions);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/Path", bstrDirPath);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/VDirName", bstrVDirName);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/DisplayName", bstrFriendlyName);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AppCreate", bstrAppCreate);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AppIsolationLevel", bstrIsoLevel);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AccessRead", bstrAccessRead);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AccessScript", bstrAccessScript);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AccessWrite", bstrAccessWrite);
|
|
if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AccessExecute", bstrAccessExecute);
|
|
|
|
|
|
// Create a IIS metabase path. ex. IIS://localhost/W3SVC/1/ROOT
|
|
bstrConfigPath = IIS_PREFIX;
|
|
|
|
// append server name, W3SVC and server number
|
|
if ( bstrServer.Length() == 0 )
|
|
bstrServer = IIS_LOCALHOST;
|
|
|
|
bstrConfigPath.AppendBSTR(bstrServer);
|
|
bstrConfigPath.Append(IIS_W3SVC);
|
|
bstrConfigPath.Append(L"/");
|
|
bstrConfigPath.AppendBSTR(bServerNumber);
|
|
|
|
// if there is a VDir name, then it must be under 'ROOT'
|
|
if ( bstrVDirName.Length() == 0 )
|
|
{
|
|
bstrVDirName = IIS_VROOT;
|
|
}
|
|
else
|
|
{
|
|
bstrConfigPath.Append(L"/");
|
|
bstrConfigPath.Append(IIS_VROOT);
|
|
}
|
|
|
|
|
|
//Step 2: Get the AppFriendlyName
|
|
if ( bstrFriendlyName.Length() == 0 )
|
|
bstrFriendlyName = IIS_VDEFAULT_APP;
|
|
|
|
// Step 3: Create a Virtual directory on new IIsWebServer configPath
|
|
CComBSTR bstrVDirAdsPath;
|
|
hr = CreateIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath,bstrVDirName, bstrFriendlyName, bstrDirPath, bstrVDirAdsPath);
|
|
IIsScoLogFailure();
|
|
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
// Step 4: set each of the properties
|
|
// Set the server bindings
|
|
CComPtr<IADs> pADs;
|
|
hr = ADsGetObject( bstrVDirAdsPath,IID_IADs, (void **)&pADs);
|
|
if ( FAILED(hr) )
|
|
{
|
|
// "DeleteVDirRollback: Failed to create IADs object for VDir path."
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Bug# 453928 -- Default AppIsolationLevel is 2
|
|
if ( !IsPositiveInteger(bstrIsoLevel))
|
|
bstrIsoLevel = IIS_DEFAULT_APPISOLATED;
|
|
|
|
// Set AppIsolationLevel -- 'AppIsolated'
|
|
if (SUCCEEDED(hr)) hr = SetVDirProperty(pADs, L"AppIsolated",bstrIsoLevel);
|
|
IIsScoLogFailure();
|
|
|
|
// Set AccessFlags'
|
|
if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
|
|
{
|
|
hr = SetVDirProperty(pADs, L"AccessRead",bstrAccessRead);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
|
|
{
|
|
hr = SetVDirProperty(pADs, L"AccessScript",bstrAccessScript);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
|
|
{
|
|
hr = SetVDirProperty(pADs, L"AccessWrite",bstrAccessWrite);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
|
|
{
|
|
hr = SetVDirProperty(pADs, L"AccessExecute",bstrAccessExecute);
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Step 5: If AppCreate is FALSE, then remove the following properties.
|
|
bstrAppCreate.ToUpper();
|
|
if ( SUCCEEDED(hr) && StringCompare(bstrAppCreate, IIS_FALSE) )
|
|
{
|
|
hr = DeleteMetaPropertyValue(pADs, L"AppIsolated");
|
|
|
|
if SUCCEEDED(hr) hr = DeleteMetaPropertyValue(pADs, L"AppRoot");
|
|
|
|
if SUCCEEDED(hr) hr = DeleteMetaPropertyValue(pADs, L"AppFriendlyName");
|
|
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
|
|
|
|
} // end if step 3
|
|
}
|
|
else
|
|
{
|
|
// L"DeleteVDirRollback: VirtualDirectory child node missing from XML DOM Rollback data."
|
|
IIsScoLogFailure();
|
|
|
|
} // end if child node
|
|
|
|
}
|
|
else
|
|
{
|
|
// L"DeleteVDirRollback: Could not load XML DOM from Rollback data."
|
|
IIsScoLogFailure();
|
|
|
|
} // end if loadXML
|
|
}
|
|
else
|
|
{
|
|
// L"DeleteVDirRollback: xml string from Rollback data NULL."
|
|
IIsScoLogFailure();
|
|
|
|
} // end if xmlString != NULL
|
|
|
|
|
|
// "DeleteVDirRollback failed."
|
|
if ( FAILED(hr) )
|
|
IIsScoLogFailure();
|
|
|
|
|
|
TRACE_EXIT(L"CIISSCO50::DeleteVDirRollback");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::SetConfigProperty_Execute
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework to set a IIS property value.
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::SetConfigProperty_Execute( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::SetConfigProperty");
|
|
|
|
HRESULT hr = S_OK;
|
|
CComBSTR bstrPathXML; // metabase path
|
|
CComBSTR bstrPropertyXML; // IIS property to set
|
|
CComBSTR bstrNewValueXML; // new property value
|
|
CComBSTR bstrOldValue; // current value for roll-back
|
|
CComBSTR bstrAdsiPath; // adsi path: IIS:// + bstrPathXML
|
|
|
|
CComPtr<IXMLDOMNode> pNode;
|
|
CComBSTR propertyXML;
|
|
|
|
// Get node in format: <executeData><Website number=''><Root />...
|
|
hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
|
|
|
|
CComBSTR bstrDebug;
|
|
hr = pNode->get_xml(&bstrDebug);
|
|
ATLTRACE(_T("\t>>>SetConfigProperty_Execute: xml = : %ls\n"), bstrDebug.m_str);
|
|
|
|
|
|
// Step 1: Get the metabase path, property name and pointer to Property Node
|
|
hr = GetInputAttr(pNode, L"./ConfigPath", L"name", bstrPathXML);
|
|
if (SUCCEEDED(hr)) hr = GetInputAttr(pNode, L"./Property", L"name", bstrPropertyXML);
|
|
if (SUCCEEDED(hr)) hr = GetInputParam(pNode, L"./Property", bstrNewValueXML);
|
|
|
|
// Step 2: Get current value
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Create a IIS metabase path. ex. IIS://W3SVC/MyServer/1
|
|
bstrAdsiPath = IIS_PREFIX;
|
|
bstrAdsiPath.AppendBSTR(bstrPathXML);
|
|
|
|
// Bind to ADs object
|
|
CComPtr<IADs> pADs;
|
|
hr = ADsGetObject(bstrAdsiPath, IID_IADs, (void**) &pADs );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = GetMetaPropertyValue(pADs, bstrPropertyXML, bstrOldValue);
|
|
IIsScoLogFailure();
|
|
|
|
//Step 3: Set property data
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, bstrPropertyXML, bstrNewValueXML);
|
|
IIsScoLogFailure();
|
|
|
|
} // End if 'GetIIsPropertyValue'
|
|
}
|
|
else
|
|
{
|
|
// "SetConfigProperty: Failed to bind to ADs object."
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
IIsScoLogFailure();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_MISSING_FIELD;
|
|
} //End if 'Step 2'
|
|
|
|
|
|
// If there is a failure
|
|
if ( FAILED(hr) )
|
|
{
|
|
// SetConfigProperty Failed
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
// convert BSTR to Variant and save in RollbackData
|
|
CComVariant varData1(bstrAdsiPath);
|
|
hr = m_pProvHelper->SetRollbackData(L"ConfigPath", varData1);
|
|
|
|
// convert BSTR to Variant and save in RollbackData
|
|
CComVariant varData2(bstrPropertyXML);
|
|
hr = m_pProvHelper->SetRollbackData(L"Property", varData2);
|
|
|
|
// convert BSTR to Variant and save in RollbackData
|
|
CComVariant varData3(bstrOldValue);
|
|
hr = m_pProvHelper->SetRollbackData(L"Value", varData3);
|
|
|
|
}
|
|
|
|
|
|
TRACE_EXIT(L"CIISSCO50::SetConfigProperty");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::SetConfigProperty_Rollback
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework to rollback a failed called
|
|
// tp 'SetMbProperty' above.
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::SetConfigProperty_Rollback( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_EXIT(L"CIISSCO50::SetConfigPropertyRollback");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
CComBSTR bstrAdsiPath;
|
|
CComBSTR bstrPropertyXML;
|
|
CComBSTR bstrOldValue;
|
|
|
|
|
|
// Get Rollback values, then convert from variants to BSTRs
|
|
CComVariant varAdsiPath;
|
|
hr = m_pProvHelper->GetRollbackData(L"ConfigPath", &varAdsiPath);
|
|
|
|
CComVariant varPropertyXML;
|
|
if (SUCCEEDED(hr)) hr = m_pProvHelper->GetRollbackData(L"Property", &varPropertyXML);
|
|
|
|
CComVariant varOldValue;
|
|
if (SUCCEEDED(hr)) hr = m_pProvHelper->GetRollbackData(L"Value", &varOldValue);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Convert to BSTRs
|
|
bstrAdsiPath = varAdsiPath.bstrVal;
|
|
bstrPropertyXML = varPropertyXML.bstrVal;
|
|
bstrOldValue = varOldValue.bstrVal;
|
|
|
|
|
|
// Bind to ADs object
|
|
CComPtr<IADs> pADs;
|
|
hr = ADsGetObject(bstrAdsiPath, IID_IADs, (void**) &pADs );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SetMetaPropertyValue(pADs, bstrPropertyXML, bstrOldValue);
|
|
IIsScoLogFailure();
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
IIsScoLogFailure();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// "SetConfigPropertyRollback: Failed to retrieve required rollback property ."
|
|
hr = E_SCO_IIS_MISSING_FIELD;
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Log failure -- SetConfigPropertyRollback Failed
|
|
if ( FAILED(hr) )
|
|
IIsScoLogFailure();
|
|
|
|
TRACE_EXIT(L"CIISSCO50::SetConfigPropertyRollback");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::GetConfigProperty_Execute
|
|
// Method: GetConfigProperty
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework to get a IIS property value.
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::GetConfigProperty_Execute( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSco50Obj::GetConfigProperty");
|
|
|
|
HRESULT hr = S_OK;
|
|
CComBSTR bstrPathXML; // metabase path
|
|
CComBSTR bstrPropertyXML; // IIS property to set
|
|
CComBSTR bstrValue; // property value
|
|
CComBSTR bstrAdsiPath; // complete IIS metabase path
|
|
CComPtr<IXMLDOMNode> pNode; // xml node <property>
|
|
|
|
// Get node in format: <executeData><Website number=''><Root />...
|
|
hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
|
|
|
|
CComBSTR bstrDebug;
|
|
hr = pNode->get_xml(&bstrDebug);
|
|
ATLTRACE(_T("\t>>>GetConfigProperty_Execute: xml = : %ls\n"), bstrDebug.m_str);
|
|
|
|
|
|
// Step 1: Get the metabase path, property name and pointer to Property Node
|
|
hr = GetInputAttr(pNode, L"./ConfigPath", L"name", bstrPathXML);
|
|
hr = GetInputAttr(pNode, L"./Property", L"name", bstrPropertyXML);
|
|
|
|
// Step 2: Get current value
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Create a IIS metabase path. ex. IIS://W3SVC/MyServer/1
|
|
bstrAdsiPath.Append(IIS_PREFIX);
|
|
bstrAdsiPath.AppendBSTR(bstrPathXML);
|
|
|
|
// Bind to ADs object
|
|
CComPtr<IADs> pADs;
|
|
hr = ADsGetObject(bstrAdsiPath, IID_IADs, (void**) &pADs );
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = GetMetaPropertyValue(pADs, bstrPropertyXML, bstrValue);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Set the element value
|
|
hr = PutElement(pNode, L"./Property", bstrValue.m_str);
|
|
|
|
// Debug render the xml
|
|
CComBSTR bstring;
|
|
hr = pNode->get_xml(&bstring);
|
|
ATLTRACE(_T("\tGetConfigProperty: %ws\n"), bstring);
|
|
|
|
IIsScoLogFailure();
|
|
|
|
}
|
|
else
|
|
{
|
|
// "GetConfigProperty: Failed to get property."
|
|
hr = E_SCO_IIS_GET_PROPERTY_FAILED;
|
|
IIsScoLogFailure();
|
|
} // End if 'GetIIsPropertyValue'
|
|
}
|
|
else
|
|
{
|
|
// "GetConfigProperty: Failed to bind to ADs object."
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
IIsScoLogFailure();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// "GetConfigProperty: Input values missing."
|
|
hr = E_SCO_IIS_MISSING_FIELD;
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// GetConfigProperty failed
|
|
if ( FAILED(hr) )
|
|
IIsScoLogFailure();
|
|
|
|
TRACE_EXIT(L"CIISSco50Obj::GetConfigProperty");
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::EnumConfig_Execute
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework to list properties on a given adsi path.
|
|
// It will also list subnodes
|
|
// This is analogous to adsutil enum /w3svc/1
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::EnumConfig_Execute( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::EnumConfig");
|
|
|
|
HRESULT hr = S_OK;
|
|
CComBSTR bstrPathXML; // metabase path
|
|
CComBSTR bstrAdsiPath; // adsi path: IIS:// + bstrPathXML
|
|
CComBSTR bstrIsInherit; // True or false to check inheritable properties
|
|
|
|
CComPtr<IXMLDOMNode> pNode;
|
|
CComPtr<IXMLDOMNode> pConfigNode;
|
|
CComPtr<IXMLDOMNode> pTemp;
|
|
CComBSTR xmlString;
|
|
|
|
// Get node in format: <executeData><Website number=''><Root />...
|
|
hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
|
|
|
|
CComBSTR bstrDebug;
|
|
hr = pNode->get_xml(&bstrDebug);
|
|
ATLTRACE(_T("\t>>>EnumConfig_Execute: xml = : %ls\n"), bstrDebug.m_str);
|
|
|
|
|
|
// Step .5: Get isInheritable flag. If blank, then default = TRUE
|
|
hr = GetInputAttr(pNode, L"./ConfigPath", XML_ATT_ISINHERITABLE, bstrIsInherit);
|
|
|
|
// Step 1: Get the metabase path
|
|
hr = GetInputAttr(pNode, L"./ConfigPath", L"name", bstrPathXML);
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Step 2 Create a IIS metabase path to find properties on. ex. IIS://W3SVC/MyServer/1
|
|
bstrAdsiPath = IIS_PREFIX;
|
|
bstrAdsiPath.AppendBSTR(bstrPathXML);
|
|
|
|
// Step 3: Returns map of all properties set on this path (not inherited)
|
|
Map myProps;
|
|
hr = EnumPropertyValue(bstrAdsiPath, bstrIsInherit, myProps);
|
|
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
// Step 4: Create the <ConfigPath> element and append to pNode
|
|
xmlString = "<ConfigPath name='";
|
|
xmlString.AppendBSTR(bstrAdsiPath);
|
|
xmlString.Append(L"'></ConfigPath>");
|
|
hr = AppendElement(pNode,xmlString,pConfigNode);
|
|
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
|
|
// Iterate through property Map and append to pNode
|
|
Map::iterator it;
|
|
for (it=myProps.begin(); it != myProps.end(); it++)
|
|
{
|
|
// Create property element: <Property name='myProp'>ItsValue</Property>
|
|
xmlString = "<Property name='";
|
|
xmlString.AppendBSTR((*it).first);
|
|
xmlString.Append(L"'>");
|
|
xmlString.AppendBSTR((*it).second);
|
|
xmlString.Append(L"</Property>");
|
|
hr = AppendElement(pConfigNode,xmlString,pTemp);
|
|
pTemp = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// "EnumConfig: Call to AppendElement failed."
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
// Step 5: Get a List of subnodes and append to pNode
|
|
Map myNode;
|
|
int iCount = 0;
|
|
hr = EnumPaths(false,bstrAdsiPath,myNode);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
// Iterate through subnodes and append to pNode
|
|
Map::iterator it;
|
|
for (it=myNode.begin(); it != myNode.end(); it++)
|
|
{
|
|
// In this case, skip the first element since it will
|
|
// be the <ConfigPath> already listed above.
|
|
if ( iCount != 0 )
|
|
{
|
|
xmlString = "<ConfigPath name='";
|
|
xmlString.AppendBSTR((*it).first);
|
|
xmlString.Append(L"' />");
|
|
hr = AppendElement(pNode,xmlString,pTemp);
|
|
pTemp = NULL;
|
|
}
|
|
iCount++;
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// "EnumConfig: Failed to enumerate paths."
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// "EnumConfig: Failed to enumerate properties."
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// "EnumConfig: Input parameter missing."
|
|
hr = E_SCO_IIS_MISSING_FIELD;
|
|
IIsScoLogFailure();
|
|
} //End if 'Step 2'
|
|
|
|
|
|
|
|
TRACE_EXIT(L"CIISSco50Obj::EnumConfig");
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CIISSCO50::EnumConfigRecursive_Execute
|
|
// Author: Russ Gibfried
|
|
// Params: [in] none
|
|
// [out] none
|
|
// Purpose: Called by MAPS framework to list properties on a given adsi path plus
|
|
// recursively list all subnodes and their properties
|
|
// This is analogous to adsutil enum_all /w3svc/1
|
|
// Note: Only mandatory and optional properties specifically set
|
|
// on a given node are listed since listing all inherited properties
|
|
// would result in a huge output to MAPS
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::EnumConfigRecursive_Execute( IXMLDOMNode *pXMLNode )
|
|
{
|
|
TRACE_ENTER(L"CIISSCO50::EnumConfigRecursive");
|
|
|
|
HRESULT hr = S_OK;
|
|
CComBSTR bstrPathXML; // metabase path
|
|
CComBSTR bstrAdsiPath; // adsi path: IIS:// + bstrPathXML
|
|
CComBSTR bstrIsInherit; // isInheritable flag (default is true)
|
|
|
|
CComPtr<IXMLDOMNode> pNode;
|
|
CComPtr<IXMLDOMNode> pConfigNode;
|
|
CComPtr<IXMLDOMNode> pTemp;
|
|
CComBSTR xmlString;
|
|
Map myNode; // map of adsi paths
|
|
Map myProps; // map of property/values
|
|
Map::iterator it1;
|
|
Map::iterator it2;
|
|
|
|
|
|
// Get node in format: <executeData><Website number=''><Root />...
|
|
hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
|
|
|
|
CComBSTR bstrDebug;
|
|
hr = pNode->get_xml(&bstrDebug);
|
|
ATLTRACE(_T("\t>>>EnumConfigRecursive_Execute: xml = : %ls\n"), bstrDebug.m_str);
|
|
|
|
|
|
// Step .5: Get isInheritable flag. If blank, then default = TRUE
|
|
hr = GetInputAttr(pNode, L"./ConfigPath", XML_ATT_ISINHERITABLE, bstrIsInherit);
|
|
|
|
// Step 1: Get the metabase path
|
|
hr = GetInputAttr(pNode, L"./ConfigPath", L"name", bstrPathXML);
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Step 2 Create a IIS metabase path to find properties on. ex. IIS://W3SVC/MyServer/1
|
|
bstrAdsiPath = IIS_PREFIX;
|
|
bstrAdsiPath.AppendBSTR(bstrPathXML);
|
|
|
|
// Step 3: Get a list of all nodes; 'true' for recursive
|
|
hr = EnumPaths(true,bstrAdsiPath,myNode);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
// Iterate through subnodes and append to pNode
|
|
for (it1=myNode.begin(); it1 != myNode.end(); it1++)
|
|
{
|
|
|
|
xmlString = "<ConfigPath name='";
|
|
xmlString.AppendBSTR((*it1).first);
|
|
xmlString.Append(L"'></ConfigPath>");
|
|
hr = AppendElement(pNode,xmlString,pConfigNode);
|
|
|
|
// Step 4: Returns map of all properties set on this path (not inherited)
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
myProps.clear();
|
|
// Pass in the path from map (ie, IIS:/w3svc/localhost/1/root )
|
|
hr = EnumPropertyValue((*it1).first,bstrIsInherit, myProps);
|
|
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
// Iterate through property Map and append to pNode
|
|
for (it2=myProps.begin(); it2 != myProps.end(); it2++)
|
|
{
|
|
// Create property element: <Property name='myProp'>ItsValue</Property>
|
|
xmlString = "<Property name='";
|
|
xmlString.AppendBSTR((*it2).first);
|
|
xmlString.Append(L"'>");
|
|
xmlString.AppendBSTR((*it2).second);
|
|
xmlString.Append(L"</Property>");
|
|
hr = AppendElement(pConfigNode,xmlString,pTemp);
|
|
pTemp = NULL;
|
|
}
|
|
|
|
// Done with pConfigNode so set it to NULL
|
|
pConfigNode = NULL;
|
|
|
|
}
|
|
else
|
|
{
|
|
// "EnumConfigRecursive: Call to EnumPropertyValue failed."
|
|
IIsScoLogFailure();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// "EnumConfigRecursive: Call to AppendElement failed."
|
|
IIsScoLogFailure();
|
|
|
|
}
|
|
|
|
} // end for myNode
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
// "EnumConfigRecursive: Failed to enumerate paths."
|
|
IIsScoLogFailure();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// "EnumConfigRecursive: Input parameter missing."
|
|
hr = E_SCO_IIS_MISSING_FIELD;
|
|
IIsScoLogFailure();
|
|
} //End if 'Step 2'
|
|
|
|
|
|
TRACE_EXIT(L"CIISSCO50::EnumConfigRecursive");
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//--------------------------- ADSI Helper Methods ------------------------------//
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: GetMetaPropertyValue
|
|
// Author: Russ Gibfried
|
|
// Params: [in] pADs -- IADs pointer to metabase path for property value
|
|
// bstrName -- name or property
|
|
// [out] pVal -- value of property
|
|
// Purpose: Return value of particular property
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::GetMetaPropertyValue(CComPtr<IADs> pADs, CComBSTR bstrName, CComBSTR& pVal)
|
|
{
|
|
HRESULT hr;
|
|
CComVariant var;
|
|
CComBSTR bValue;
|
|
|
|
hr = pADs->Get(bstrName, &var);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
switch (var.vt)
|
|
{ case VT_EMPTY:
|
|
{
|
|
break;
|
|
}
|
|
case VT_NULL:
|
|
{
|
|
break;
|
|
}
|
|
case VT_I4:
|
|
{
|
|
hr = var.ChangeType(VT_BSTR);
|
|
if ( SUCCEEDED(hr) ) pVal = V_BSTR(&var);
|
|
|
|
break;
|
|
}
|
|
case VT_BSTR:
|
|
{
|
|
pVal = V_BSTR(&var);
|
|
break;
|
|
}
|
|
case VT_BOOL:
|
|
{
|
|
|
|
if (var.boolVal == 0)
|
|
{
|
|
pVal = L"False";
|
|
}
|
|
else
|
|
{
|
|
pVal = L"True";
|
|
}
|
|
break;
|
|
}
|
|
case VT_ARRAY|VT_VARIANT: // SafeArray of Variants
|
|
{
|
|
|
|
LONG lstart, lend;
|
|
SAFEARRAY *sa = V_ARRAY( &var );
|
|
VARIANT varItem;
|
|
|
|
// Get the lower and upper bound
|
|
hr = SafeArrayGetLBound( sa, 1, &lstart );
|
|
hr = SafeArrayGetUBound( sa, 1, &lend );
|
|
|
|
// Now iterate and print the content
|
|
VariantInit(&varItem);
|
|
CComBSTR bString;
|
|
for ( long idx=lstart; idx <= lend; idx++ )
|
|
{
|
|
hr = SafeArrayGetElement( sa, &idx, &varItem );
|
|
pVal = V_BSTR(&varItem);
|
|
VariantClear(&varItem);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case VT_DISPATCH:
|
|
{
|
|
//if (!_wcsicmp(bstrName, L"ipsecurity"))
|
|
break;
|
|
}
|
|
default:
|
|
{ break;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if ( FAILED(hr))
|
|
hr = E_SCO_IIS_GET_PROPERTY_FAILED;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: SetMetaPropertyValue
|
|
// Author: Russ Gibfried
|
|
// Params: [in] pADs -- pointer to metabase path object; ie 'IIS://MachineName/W3SVC/1'
|
|
// bstrName -- name or property
|
|
// bstrValue -- property value to set
|
|
// [out] none
|
|
// Purpose: Set the value of particular a particular property
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::SetMetaPropertyValue(CComPtr<IADs> pADs, CComBSTR bstrName, CComBSTR bstrValue)
|
|
{
|
|
HRESULT hr = E_SCO_IIS_SET_PROPERTY_FAILED;
|
|
|
|
|
|
hr = pADs->Put(bstrName, CComVariant(bstrValue));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pADs->SetInfo();
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: DeleteMetaPropertyValue
|
|
// Author: Russ Gibfried
|
|
// Params: [in] pADs -- pointer to metabase path object; ie 'IIS://MachineName/W3SVC/1'
|
|
// bstrName -- name or property
|
|
// bstrValue -- property value to set
|
|
// [out] none
|
|
// Purpose: Set the value of particular a particular property
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::DeleteMetaPropertyValue(CComPtr<IADs> pADs, CComBSTR bstrName)
|
|
{
|
|
HRESULT hr = E_SCO_IIS_SET_PROPERTY_FAILED;
|
|
|
|
|
|
VARIANT vProp;
|
|
VariantInit(&vProp);
|
|
hr = pADs->PutEx(1, bstrName, vProp); // 1 = Clear
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pADs->SetInfo();
|
|
}
|
|
|
|
VariantClear(&vProp);
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: CreateIIs50Site
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bstrType -- 'Type' of site, ie 'IIsWebServer' or 'IIsFtpServer
|
|
// bWebADsPath -- AdsPath, ex. IIS:/localhost/w3svc
|
|
// bSiteIndex -- Site number, ie, 1
|
|
|
|
// [out] bstrConfigPath -- craeted adsi path, ex. IIS://localhost/W3SVC/1
|
|
// Purpose: Set the value of particular a particular property
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::CreateIIs50Site(CComBSTR bstrType,CComBSTR bWebADsPath,
|
|
CComBSTR bServerNumber,CComBSTR &bstrConfigPath)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IADs> pADs;
|
|
CComPtr<IADsContainer> pCont;
|
|
IDispatch* pDisp;
|
|
CComVariant var;
|
|
|
|
// Bind to a domain object: 'IIS://MachineName/W3SVC'
|
|
hr = ADsGetObject( bWebADsPath,IID_IADsContainer, (void **)&pCont);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
//Create a virtual web server
|
|
hr = pCont->Create(bstrType,bServerNumber,&pDisp);
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
|
|
// Get the newly created ConfigPath value
|
|
hr = pDisp->QueryInterface(IID_IADs, (void**)&pADs);
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
// Release the IDispath pointer
|
|
pDisp->Release();
|
|
|
|
// Get the newly created ADsPath for this Server
|
|
if (SUCCEEDED(hr)) hr = pADs->get_ADsPath(&bstrConfigPath);
|
|
hr = pADs->SetInfo();
|
|
|
|
// Return the correct HRESULT depending is Web Site of FTP Site
|
|
if (FAILED(hr))
|
|
{
|
|
if (StringCompare(bstrType,IIS_IISWEBSERVER))
|
|
{
|
|
hr = E_SCO_IIS_CREATE_WEB_FAILED;
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_CREATE_FTP_FAILED;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
} // end if Create
|
|
else
|
|
{
|
|
// Return the correct HRESULT depending is Web Site of FTP Site
|
|
if (StringCompare(bstrType,IIS_IISWEBSERVER))
|
|
{
|
|
hr = E_SCO_IIS_CREATE_WEB_FAILED;
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_CREATE_FTP_FAILED;
|
|
}
|
|
}
|
|
|
|
} // end if ADsGetObject
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: DeleteIIs50Site
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bstrType -- 'Type' of site, ie 'IIsWebServer' or 'IIsFtpServer
|
|
// bWebADsPath -- server adsi path ex. IIS://localhost/W3SVC
|
|
// bServerNumber -- Server index number to delete
|
|
// Purpose: Delete a Web or FTP server
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::DeleteIIs50Site(CComBSTR bstrType,CComBSTR bWebADsPath,CComBSTR bServerNumber)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IADsContainer> pCont;
|
|
|
|
// Bind to a domain object: 'IIS://MachineName/W3SVC'
|
|
hr = ADsGetObject( bWebADsPath,IID_IADsContainer, (void **)&pCont);
|
|
|
|
//Delete a virtual web server
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pCont->Delete(bstrType,bServerNumber);
|
|
if (FAILED(hr))
|
|
{
|
|
|
|
// Return the correct HRESULT depending is Web Site of FTP Site
|
|
if (StringCompare(bstrType,IIS_IISWEBSERVER))
|
|
{
|
|
hr = E_SCO_IIS_DELETE_WEB_FAILED;
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_DELETE_FTP_FAILED;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_ADSCONTAINER_CREATE_FAILED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: CreateIIs50VDir
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bstrType -- 'Type' of site, ie 'IIsWebVirtualDir"
|
|
// bWebADsPath -- IIS://localhost/W3SVC/1
|
|
// bVDirName -- url, ex. 'ROOT'
|
|
// bAppFriendName -- 'Default Application'
|
|
// bVDirPath -- url, ex. c:/inetpub/myDir
|
|
//
|
|
// [out] bstrConfigPath -- created adsi path, ex. IIS://localhost/W3SVC/1/ROOT
|
|
// Purpose: Set the value of particular a particular property
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::CreateIIs50VDir(CComBSTR bstrType,CComBSTR bWebADsPath, CComBSTR bVDirName,
|
|
CComBSTR bAppFriendName, CComBSTR bVDirPath,CComBSTR &bstrConfigPath)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IADs> pADs;
|
|
CComPtr<IADsContainer> pCont;
|
|
IDispatch* pDisp;
|
|
CComVariant var;
|
|
|
|
|
|
// Bind to a domain object: 'IIS://MachineName/W3SVC/1'
|
|
hr = ADsGetObject( bWebADsPath,IID_IADsContainer, (void **)&pCont);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
//Create a virtual directory for web server
|
|
hr = pCont->Create(bstrType,bVDirName,&pDisp);
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
|
|
// Get the newly created ConfigPath value
|
|
hr = pDisp->QueryInterface(IID_IADs, (void**)&pADs);
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
|
|
// Release the IDispath pointer
|
|
pDisp->Release();
|
|
|
|
// Set Root path and AccessRead
|
|
if (SUCCEEDED(hr)) hr = pADs->Put(L"Path",CComVariant(bVDirPath));
|
|
if (SUCCEEDED(hr)) hr = pADs->Put(L"AccessRead",CComVariant(L"TRUE"));
|
|
|
|
// Get the newly created ADsPath for this Server
|
|
if (SUCCEEDED(hr)) hr = pADs->get_ADsPath(&bstrConfigPath);
|
|
|
|
// Set the info
|
|
if (SUCCEEDED(hr)) hr = pADs->SetInfo();
|
|
|
|
//-----------------------------------------------------
|
|
// RG: Now call AppCreate through IDispatch to set the application
|
|
// Note: This only seems to work for 'IIsWebVirtualDir'??
|
|
//-----------------------------------------------------
|
|
if ( bstrType == "IIsWebVirtualDir" && SUCCEEDED(hr) )
|
|
{
|
|
DISPID dispid;
|
|
LPOLESTR str = OLESTR("AppCreate");
|
|
|
|
// Get a pointer to IDispatch from object
|
|
hr = pCont->GetObject(bstrType,bVDirName,&pDisp);
|
|
|
|
// See if object supports 'AppCreate' and dispid
|
|
if (SUCCEEDED(hr)) hr = pDisp->GetIDsOfNames(IID_NULL, &str, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
|
|
|
|
// Set the parameters
|
|
VARIANT myVars[1];
|
|
VariantInit(&myVars[0]);
|
|
myVars[0].vt = VT_BOOL;
|
|
myVars[0].boolVal = true;
|
|
|
|
DISPPARAMS params = {myVars,0,1,0};
|
|
|
|
// Invoke 'AppCreate'
|
|
if (SUCCEEDED(hr)) hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
|
|
DISPATCH_METHOD,¶ms, NULL, NULL, NULL);
|
|
|
|
// Cleanup
|
|
if (SUCCEEDED(hr)) hr = pDisp->Release();
|
|
//VariantClear(&myVars);
|
|
|
|
// Set AppFriendlyName
|
|
if (SUCCEEDED(hr)) hr = pADs->Put(L"AppFriendlyName",CComVariant(bAppFriendName));
|
|
|
|
// Set the info
|
|
if (SUCCEEDED(hr)) hr = pADs->SetInfo();
|
|
|
|
}
|
|
|
|
// Check for failure
|
|
if ( FAILED(hr)) hr = E_SCO_IIS_CREATE_VDIR_FAILED;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
}
|
|
|
|
} // end if Create
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_CREATE_VDIR_FAILED;
|
|
}
|
|
|
|
} // end if ADsGetObject
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_ADSCONTAINER_CREATE_FAILED;
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: DeleteIIs50VDir
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bstrType -- 'Type' of site, ie 'IIsWebVirtualDir"
|
|
// bWebADsPath -- IIS://localhost/W3SVC/1
|
|
// bVDirName -- url, ex. 'ROOT'
|
|
//
|
|
// [out] bstrConfigPath -- created adsi path, ex. IIS://localhost/W3SVC/1/ROOT
|
|
// Purpose: Set the value of particular a particular property
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::DeleteIIs50VDir(CComBSTR bstrType,CComBSTR bWebADsPath, CComBSTR bVDirName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IADsContainer> pCont;
|
|
IDispatch* pDisp;
|
|
|
|
|
|
|
|
// Bind to a domain object: 'IIS://MachineName/W3SVC/1'
|
|
hr = ADsGetObject( bWebADsPath,IID_IADsContainer, (void **)&pCont);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
//-----------------------------------------------------
|
|
// RG: Now call AppDelete through IDispatch to set the application
|
|
//-----------------------------------------------------
|
|
DISPID dispid;
|
|
LPOLESTR str = OLESTR("AppDelete");
|
|
|
|
// Get a pointer to IDispatch from object
|
|
if (SUCCEEDED(hr)) hr = pCont->GetObject(bstrType,bVDirName,&pDisp);
|
|
|
|
// See if object supports 'AppCreate' and dispid
|
|
if (SUCCEEDED(hr)) hr = pDisp->GetIDsOfNames(IID_NULL, &str, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
|
|
|
|
// Set the parameters
|
|
//VARIANT myVars[1];
|
|
//VariantInit(&myVars[0]);
|
|
//myVars[0].vt = VT_BOOL;
|
|
///myVars[0].boolVal = true;
|
|
|
|
DISPPARAMS params = {NULL,NULL,0,0};
|
|
|
|
// Invoke 'AppCreate'
|
|
if (SUCCEEDED(hr)) hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
|
|
DISPATCH_METHOD,¶ms, NULL, NULL, NULL);
|
|
|
|
// Cleanup
|
|
if (SUCCEEDED(hr)) hr = pDisp->Release();
|
|
//VariantClear(&myVars);
|
|
|
|
|
|
//Delete the virtual directory at VDirName
|
|
if (SUCCEEDED(hr)) hr = pCont->Delete(bstrType,bVDirName);
|
|
|
|
if ( FAILED(hr) )
|
|
hr = E_SCO_IIS_DELETE_VDIR_FAILED;
|
|
|
|
|
|
} // end if ADsGetObject
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_ADSCONTAINER_CREATE_FAILED;
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: SetVDirProperty
|
|
// Author: Russ Gibfried
|
|
// Params: [in]
|
|
// pADs -- pointer to ADs object for something like IIS://localhost/W3SVC/1/ROOT
|
|
// bVDirProperty -- , ex. 'AuthFlags'
|
|
// bVDirValue -- property value
|
|
//
|
|
// [out] none
|
|
// Purpose: Set the value of particular a particular property for a Virtual Directory
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::SetVDirProperty(CComPtr<IADs> pADs, CComBSTR bVDirProperty,CComBSTR bVDirValue)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
// Bind to a domain object: 'IIS://MachineName/W3SVC/1/ROOT'
|
|
if ( pADs != NULL )
|
|
{
|
|
|
|
// Set the property
|
|
hr = pADs->Put(bVDirProperty,CComVariant(bVDirValue));
|
|
|
|
// Set the info
|
|
if (SUCCEEDED(hr)) hr = pADs->SetInfo();
|
|
|
|
|
|
} // end if ADsGetObject
|
|
|
|
if ( FAILED(hr))
|
|
hr = E_SCO_IIS_SET_PROPERTY_FAILED;
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: EnumPaths
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bRecursive -- Boolean; true to recursely iterate through subnodes
|
|
// bstrPath -- metabase path for key to Enumerate
|
|
// [out] variant SafeArray
|
|
// Purpose: Enumerate the keys/nodes for a given ADsPath
|
|
// Example: IIS://localhost/W3SVC/1 yields IISCertMapper and Root
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::EnumPaths(BOOL bRecursive,CComBSTR bstrPath, Map& mVar)
|
|
{
|
|
//initialize
|
|
HRESULT hr = E_FAIL;
|
|
IADs *pADs;
|
|
CComPtr<IADsContainer> pCont;
|
|
VARIANT var;
|
|
ULONG lFetch;
|
|
IDispatch *pDisp;
|
|
IEnumVARIANT *pEnum;
|
|
|
|
|
|
// Get the container object for given ADsPath
|
|
hr = ADsGetObject(bstrPath, IID_IADsContainer, (void**) &pCont );
|
|
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
//add to Map
|
|
mVar[bstrPath] = bstrPath;
|
|
|
|
// Create a Enum object in container
|
|
hr = ADsBuildEnumerator(pCont, &pEnum);
|
|
|
|
// Walk through all providers
|
|
while (hr == S_OK)
|
|
{
|
|
hr = ADsEnumerateNext(pEnum,1,&var,&lFetch);
|
|
if ( lFetch == 1)
|
|
{
|
|
pDisp = V_DISPATCH(&var);
|
|
pDisp->QueryInterface(IID_IADs, (void**)&pADs);
|
|
pDisp->Release();
|
|
|
|
BSTR bstr;
|
|
pADs->get_ADsPath(&bstr);
|
|
pADs->Release();
|
|
|
|
// true if we are to recursively navigate lower nodes
|
|
if ( bRecursive )
|
|
{
|
|
EnumPaths(bRecursive,bstr, mVar);
|
|
}
|
|
else
|
|
{
|
|
mVar[bstr] = bstr;
|
|
}
|
|
|
|
SysFreeString(bstr);
|
|
|
|
|
|
}
|
|
}
|
|
|
|
if ( pEnum )
|
|
ADsFreeEnumerator(pEnum);
|
|
}
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: EnumPropertyValue
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bstrPath -- metabase path for key to Enumerate
|
|
// [in] bstrIsInHerit -- True/False if required to display inheritable properties
|
|
// [out] variant SafeArray
|
|
// Purpose: Make sure IIS://localhost/W3SVC/2
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::EnumPropertyValue(CComBSTR bstrPath, CComBSTR bstrIsInHerit, Map& mVar)
|
|
{
|
|
//initialize
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IADs> pADs;
|
|
CComPtr<IADsClass> pCls;
|
|
CComBSTR bstrSchema;
|
|
|
|
CComPtr<IISBaseObject> pBase;
|
|
|
|
// variables for SafeArray or properties
|
|
LONG lstart, lend;
|
|
CComBSTR bstrProperty;
|
|
CComBSTR bstrValue;
|
|
|
|
// Set bstrIsInHerit to uppercase
|
|
bstrIsInHerit.ToUpper();
|
|
|
|
// Bind to a domain object -- this will give us schema, class and name
|
|
hr = ADsGetObject(bstrPath, IID_IADs, (void**) &pADs );
|
|
if ( SUCCEEDED(hr)) hr = pADs->get_Schema(&bstrSchema);
|
|
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
// Bind to IIS Admin Object so we can determine if properties are inherited or not
|
|
hr = ADsGetObject(bstrPath, IID_IISBaseObject, (void**) &pBase );
|
|
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
// Bind to schema object and get all optional properties
|
|
hr = ADsGetObject(bstrSchema,IID_IADsClass, (void**)&pCls);
|
|
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
//********** Get Mandatory Properties ************************
|
|
VARIANT varProperty;
|
|
VariantInit(&varProperty);
|
|
hr = pCls->get_MandatoryProperties(&varProperty);
|
|
|
|
// iterate through properties
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
VARIANT varItem;
|
|
SAFEARRAY *sa = V_ARRAY( &varProperty );
|
|
hr = SafeArrayGetLBound( sa, 1, &lstart );
|
|
hr = SafeArrayGetUBound( sa, 1, &lend );
|
|
VariantInit(&varItem);
|
|
|
|
// For loop through properties
|
|
for ( long idx=lstart; idx <= lend; idx++ )
|
|
{
|
|
// Get a property
|
|
hr = SafeArrayGetElement( sa, &idx, &varItem );
|
|
bstrProperty = V_BSTR(&varItem);
|
|
VariantClear(&varItem);
|
|
|
|
// if isInheriable = false, then properties must be set on path
|
|
if ( SUCCEEDED(hr) && !StringCompare(bstrIsInHerit, IIS_FALSE) )
|
|
{
|
|
// True -- just return property
|
|
hr = GetMetaPropertyValue(pADs, bstrProperty, bstrValue);
|
|
if ( SUCCEEDED(hr) ) mVar[bstrProperty] = bstrValue;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// False -- Check if property set on this path
|
|
if ( EnumIsSet(pBase,bstrPath,bstrProperty))
|
|
{
|
|
// This property was set on this path. Get the value and add to map
|
|
hr = GetMetaPropertyValue(pADs, bstrProperty, bstrValue);
|
|
if ( SUCCEEDED(hr) ) mVar[bstrProperty] = bstrValue;
|
|
}
|
|
}
|
|
|
|
} // end For
|
|
|
|
}
|
|
|
|
//********** Repeat for Optional Properties ************************
|
|
VariantClear(&varProperty);
|
|
VariantInit(&varProperty);
|
|
hr = pCls->get_OptionalProperties(&varProperty);
|
|
|
|
// iterate through properties
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
VARIANT varItem;
|
|
SAFEARRAY *sa = V_ARRAY( &varProperty );
|
|
hr = SafeArrayGetLBound( sa, 1, &lstart );
|
|
hr = SafeArrayGetUBound( sa, 1, &lend );
|
|
VariantInit(&varItem);
|
|
|
|
// For loop through properties
|
|
for ( long idx=lstart; idx <= lend; idx++ )
|
|
{
|
|
// Get a property
|
|
hr = SafeArrayGetElement( sa, &idx, &varItem );
|
|
bstrProperty = V_BSTR(&varItem);
|
|
VariantClear(&varItem);
|
|
|
|
// if isInheriable = false, then properties must be set on path
|
|
if ( SUCCEEDED(hr) && !StringCompare(bstrIsInHerit, IIS_FALSE) )
|
|
{
|
|
// True -- just return property
|
|
hr = GetMetaPropertyValue(pADs, bstrProperty, bstrValue);
|
|
if ( SUCCEEDED(hr) ) mVar[bstrProperty] = bstrValue;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// False -- Check if property set on this path
|
|
if ( EnumIsSet(pBase,bstrPath,bstrProperty))
|
|
{
|
|
// This property was set on this path. Get the value and add to map
|
|
hr = GetMetaPropertyValue(pADs, bstrProperty, bstrValue);
|
|
if ( SUCCEEDED(hr) ) mVar[bstrProperty] = bstrValue;
|
|
}
|
|
}
|
|
|
|
|
|
} // end For
|
|
|
|
|
|
} // end if
|
|
VariantClear(&varProperty);
|
|
}
|
|
else
|
|
{
|
|
// failed to bind to schema
|
|
hr = E_SCO_IIS_ADSCLASS_CREATE_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// failed to bind to IIS BaseObject
|
|
hr = E_SCO_IIS_BASEADMIN_CREATE_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// failed to bind to ADs Object
|
|
hr = E_SCO_IIS_ADS_CREATE_FAILED;
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: EnumIsSet
|
|
// Params: [in] pBase -- pointer to IISBaseObject for given 'bstrPath'
|
|
// bstrPath -- adsi Path; IIS://localhost/W3SVC/2
|
|
// bstrProperty -- property found in schema for this path
|
|
// [out] Boolean - True is the property was set for given path and not
|
|
// inherited from another key.
|
|
// Purpose: Function checks the paths returned by 'GetDataPaths' for a given property
|
|
// to current path to determine if property was actually set at this path.
|
|
//
|
|
// Note: You can easily extend this function by adding a flag to only check
|
|
// for inheritable properties, all properties or non-inheritable.
|
|
//-------------------------------------------------------------
|
|
BOOL CIISSCO50::EnumIsSet(CComPtr<IISBaseObject> pBase, CComBSTR bstrPath, CComBSTR bstrProperty)
|
|
{
|
|
VARIANT pvPaths; // list of paths returned by 'GetDataPaths'
|
|
VARIANT *varPath; // property path
|
|
SAFEARRAY *PathArray; // SafeArray to hold pvPaths
|
|
BOOL bFound = false;
|
|
HRESULT hr;
|
|
|
|
// Get Property paths
|
|
VariantInit(&pvPaths);
|
|
VariantClear(&pvPaths);
|
|
|
|
// Check if this is a inheritable property
|
|
hr = pBase->GetDataPaths(bstrProperty,1,&pvPaths);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
//Any property
|
|
PathArray = pvPaths.parray;
|
|
varPath = (VARIANT*)PathArray->pvData;
|
|
|
|
if ( varPath->vt == VT_BSTR)
|
|
{
|
|
if ( !_wcsicmp(varPath->bstrVal,bstrPath.m_str) )
|
|
{
|
|
// This property was set on this path.
|
|
bFound = true;
|
|
}
|
|
}
|
|
}
|
|
// Check if this is not an inheritable property
|
|
else
|
|
{
|
|
VariantClear(&pvPaths);
|
|
VariantInit(&pvPaths);
|
|
hr = pBase->GetDataPaths(bstrProperty,0,&pvPaths);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
//Inheritable property
|
|
PathArray = pvPaths.parray;
|
|
varPath = (VARIANT*)PathArray->pvData;
|
|
if ( varPath->vt == VT_BSTR)
|
|
{
|
|
if ( !_wcsicmp(varPath->bstrVal,bstrPath.m_str))
|
|
{
|
|
// This property was set on this path. Get the value and add to map
|
|
bFound = true;
|
|
|
|
}
|
|
}
|
|
|
|
} // end if GetDataPaths -- IIS_ANY_PROPERTY
|
|
|
|
} // end if GetDataPaths -- IIS_INHERITABLE_ONLY
|
|
|
|
VariantClear(&pvPaths);
|
|
return bFound;
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: IIsServerAction
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bWebADsPath -- IIS://localhost/W3SVC/1
|
|
// action -- Start, Stop or Pause
|
|
//
|
|
// [out] HRESULT
|
|
// Purpose: Start, stop or pause a web site
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::IIsServerAction(CComBSTR bWebADsPath,IIsAction action)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
CComPtr<IADsServiceOperations> pService;
|
|
|
|
|
|
// Bind to a domain object: 'IIS://MachineName/W3SVC/1'
|
|
hr = ADsGetObject( bWebADsPath,IID_IADsServiceOperations, (void **)&pService);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Perform the action on the server
|
|
switch ( action )
|
|
{
|
|
|
|
// Start the server
|
|
case start:
|
|
hr = pService->Start();
|
|
break;
|
|
|
|
// Stop the server
|
|
case stop:
|
|
hr = pService->Stop();
|
|
break;
|
|
|
|
// Pause the Server
|
|
case pause:
|
|
hr = pService->Pause();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
} // end switch
|
|
} // end if
|
|
else
|
|
{
|
|
hr = E_SCO_IIS_ADSSERVICE_CREATE_FAILED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: GetNextIndex
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bstrPath -- metabase path for IIsWebService
|
|
// bstrName -- name or property
|
|
// bstrValue -- property value to set
|
|
// [out] none
|
|
// Purpose: Set the value of particular a particular property
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::GetNextIndex(CComBSTR bstrPath, CComBSTR& pIndex)
|
|
{
|
|
// initialize
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IADs> pObj;
|
|
long lCount = 1;
|
|
CComVariant var = lCount;
|
|
|
|
// initialize starting path: IIS://MyServer/W3SVC/
|
|
CComBSTR tempPath = bstrPath.Copy();
|
|
tempPath.Append(L"/");
|
|
|
|
// Append 1 to starting path: IIS://MyServer/W3SVC/1
|
|
var.ChangeType(VT_BSTR);
|
|
tempPath.Append(var.bstrVal);
|
|
|
|
// Loop through each server until fails, then we have the next server number
|
|
try
|
|
{
|
|
while ( SUCCEEDED( ADsGetObject( tempPath,IID_IADs, (void **)&pObj) ))
|
|
{
|
|
lCount++;
|
|
tempPath = bstrPath.Copy();
|
|
tempPath.Append(L"/");
|
|
var = lCount;
|
|
var.ChangeType(VT_BSTR);
|
|
tempPath.Append(var.bstrVal);
|
|
pObj = NULL;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
// unhandled exception
|
|
hr=E_FAIL;
|
|
}
|
|
|
|
var.ChangeType(VT_BSTR);
|
|
ChkAllocBstr(pIndex,var.bstrVal);
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Method: CreateBindingString
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bstrIP -- site IP
|
|
// bstrPort -- site port
|
|
// bstrHostName -- site HostName
|
|
// [out] bstrString -- server binding string
|
|
// Purpose: Creates a binding string in the format IP:Port:Hostname.
|
|
// Used in other methods to check existing server bindings and
|
|
// set new bindings. Both the IP and Hostname parameter of the string are optional.
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT CIISSCO50::CreateBindingString(CComBSTR bstrIP,CComBSTR bstrPort,
|
|
CComBSTR bstrHostName,CComBSTR& bstrString)
|
|
{
|
|
bstrString.AppendBSTR(bstrIP);
|
|
bstrString.Append(L":");
|
|
bstrString.AppendBSTR(bstrPort);
|
|
bstrString.Append(L":");
|
|
bstrString.AppendBSTR(bstrHostName);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Method: CheckBindings
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bWebADsPath -- ADs path to bind to search
|
|
// bstrNewBindings -- site IP
|
|
// [out] none
|
|
// Purpose: This compares current server bindings to the requested new bindings
|
|
// to make sure there is not a duplicate server already running. Binding
|
|
// string format is IP:Port:Hostname.
|
|
//
|
|
// Note Both the IP and Hostname parameter of the string are optional.
|
|
// Any unspecified parameters default to an all-inclusive wildcard.
|
|
//
|
|
// Metabase Path Key Type
|
|
// /LM/MSFTPSVC/N IIsFtpServer
|
|
// /LM/W3SVC/N IIsWebServer
|
|
//-------------------------------------------------------------------------------
|
|
HRESULT CIISSCO50::CheckBindings(CComBSTR bWebADsPath, CComBSTR bstrNewBindings)
|
|
{
|
|
// initialize
|
|
HRESULT hr = E_FAIL;
|
|
CComPtr<IADsContainer> pCont;
|
|
IADs* pADs;
|
|
CComVariant vBindings;
|
|
BSTR bstr;
|
|
IEnumVARIANT* pEnum;
|
|
LPUNKNOWN pUnk;
|
|
VARIANT var;
|
|
IDispatch *pDisp;
|
|
ULONG lFetch;
|
|
VariantInit(&var);
|
|
|
|
// Get a container to IIsWebService object
|
|
hr = ADsGetObject(bWebADsPath, IID_IADsContainer, (void**) &pCont );
|
|
if ( !SUCCEEDED(hr) )
|
|
{
|
|
return E_SCO_IIS_ADSCONTAINER_CREATE_FAILED;
|
|
}
|
|
|
|
// Get an enumeration of all objects below it
|
|
pCont->get__NewEnum(&pUnk);
|
|
|
|
pUnk->QueryInterface(IID_IEnumVARIANT, (void**) &pEnum);
|
|
pUnk->Release();
|
|
|
|
// Now Enumerate through objects
|
|
hr = pEnum->Next(1, &var, &lFetch);
|
|
while(hr == S_OK)
|
|
{
|
|
if (lFetch == 1)
|
|
{
|
|
pDisp = V_DISPATCH(&var);
|
|
pDisp->QueryInterface(IID_IADs, (void**)&pADs);
|
|
|
|
pDisp->Release();
|
|
pADs->get_Class(&bstr); // Debug to see Class
|
|
SysFreeString(bstr);
|
|
|
|
hr = pADs->Get(L"ServerBindings",&vBindings);
|
|
|
|
// Check server bindings for this class
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
|
|
LONG lstart, lend;
|
|
SAFEARRAY *sa = V_ARRAY( &vBindings );
|
|
VARIANT varItem;
|
|
|
|
// Get the lower and upper bound
|
|
hr = SafeArrayGetLBound( sa, 1, &lstart );
|
|
hr = SafeArrayGetUBound( sa, 1, &lend );
|
|
|
|
// Now iterate and print the content
|
|
VariantInit(&varItem);
|
|
CComBSTR bString;
|
|
for ( long idx=lstart; idx <= lend; idx++ )
|
|
{
|
|
hr = SafeArrayGetElement( sa, &idx, &varItem );
|
|
|
|
bString = V_BSTR(&varItem);
|
|
VariantClear(&varItem);
|
|
}
|
|
|
|
// Checkbindings. If match then fail;
|
|
if ( bstrNewBindings == bString)
|
|
{
|
|
hr = E_SCO_IIS_DUPLICATE_SITE;
|
|
pEnum->Release();
|
|
VariantClear(&var);
|
|
goto Leave;
|
|
|
|
}
|
|
|
|
} // end if 'bindings'
|
|
|
|
} // end if 'enum'
|
|
|
|
VariantClear(&var);
|
|
hr = pEnum->Next(1, &var, &lFetch);
|
|
|
|
}; // end while
|
|
|
|
pEnum->Release();
|
|
|
|
Leave:
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: AddBackSlashesToString
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bString -- BSTR to parse; ie 'redmond\bob:F'
|
|
//
|
|
// [out] bString -- 'redmond\\bob:F'
|
|
// Purpose: If string has only one backslash, add two since backslash is an
|
|
// escape character.
|
|
//-------------------------------------------------------------
|
|
void CIISSCO50::AddBackSlashesToString(CComBSTR& bString)
|
|
{
|
|
|
|
// initialize variables
|
|
size_t start, length, db; // string counters
|
|
start = 0; // start of string
|
|
db = 0; // index if '\\' found ( db = double backslash)
|
|
|
|
|
|
// Convert the BSTR to a std:string
|
|
USES_CONVERSION;
|
|
std::string s = OLE2A(bString.m_str);
|
|
std::string temp1,temp2,temp3 = "";
|
|
length = s.length();
|
|
|
|
// Loop through string looking for single slashes
|
|
for (size_t pos = s.find("\\")+1; pos < length; pos = s.find("\\", pos+2)+1)
|
|
{
|
|
// pos = 0 when it goes off end of string
|
|
if ( pos == 0 ) break;
|
|
|
|
// find location of double slash
|
|
db = s.find("\\\\",pos-2)+1;
|
|
|
|
// pos is the location of a single slash, if it matches db then we really have
|
|
// the first part of a double slash; so skip
|
|
if ( pos != db )
|
|
{
|
|
// replace the single slash with a double '\\'
|
|
temp1 = s.substr(start,pos-1);
|
|
temp2 = s.substr(pos,length);
|
|
s = temp1 + "\\\\" + temp2;
|
|
}
|
|
}
|
|
|
|
// return
|
|
bString = A2BSTR(s.c_str());
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: ParseBSTR
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bString -- BSTR to parse; ie 'redmond\bob:F'
|
|
// delim -- deliminator; ie ':' or 'IIS://'
|
|
// iFirstPiece -- starting piece of BSTR to return; ie 1
|
|
// iLastPiece -- ending piece of BSTR to return; ie 99
|
|
//
|
|
// [out] pVal -- piece of BSTR; ie, 'redmond\bob'
|
|
// Purpose: uses std:string functionality to parse an BSTR given a deliminator
|
|
// and which part of BSTR should be returned.
|
|
// ex) bString = "IIS://localhost/W3SVC/1/ROOT/1
|
|
// (bString,1,99,'host') --> /W3SVC/1/ROOT/1
|
|
// (bString,2,3,'/') --> localhost
|
|
// (bString,4,99,'/') --> 1
|
|
// (bString,2,4,'/') --> localhost/W3SVC
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::ParseBSTR(CComBSTR bString,CComBSTR sDelim, int iFirstPiece, int iLastPiece,CComBSTR &pVal)
|
|
{
|
|
|
|
// ------ initialize variables ------------------
|
|
// start = begining of substring
|
|
// end = end of substring
|
|
// count = counter of number of deliminators found
|
|
// done = variable to end while loop for each piece
|
|
// length = length of original string
|
|
//--------------------------------------
|
|
HRESULT hr = S_OK;
|
|
size_t start,end;
|
|
int iCount, done, iLength;
|
|
done = start = end = 0;
|
|
iCount = 0; // first piece to look for.
|
|
|
|
// If last piece is not greater that fist then end
|
|
if ( iLastPiece < iFirstPiece)
|
|
done=1;
|
|
|
|
USES_CONVERSION;
|
|
// deliminator
|
|
std::string myDelim = OLE2A(sDelim.m_str);
|
|
long iDelimLen = myDelim.length();
|
|
|
|
// my string
|
|
std::string myString = OLE2A(bString.m_str);
|
|
iLength = myString.length();
|
|
|
|
// temp and new string
|
|
std::string newString = "";
|
|
std::string tmpString = "";
|
|
|
|
while (!done)
|
|
{
|
|
// find the start of the piece
|
|
end = myString.find(myDelim,start);
|
|
|
|
if ( iCount >= iFirstPiece && iCount <= (iLastPiece-1))
|
|
{
|
|
//we want this piece
|
|
tmpString = myString.substr(start,end-start);
|
|
newString.append(tmpString);
|
|
|
|
// if iCount < iLastPiece and we're not at the end, then append deliminator too
|
|
if ( iCount < (iLastPiece-1) && end < iLength)
|
|
newString.append(myDelim);
|
|
}
|
|
|
|
// if we have gone passed end of string quit, else increment
|
|
// deliminator and string counters.
|
|
if ( end >= iLength || iCount >= (iLastPiece-1))
|
|
{
|
|
done = 1;
|
|
}
|
|
else
|
|
{
|
|
start = end + iDelimLen; // increment start
|
|
iCount++;
|
|
}
|
|
|
|
}
|
|
|
|
//convert string back to BSTR -- A2BSTR
|
|
pVal = A2BSTR(newString.c_str());
|
|
|
|
return hr;
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: NumberOfDelims
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bString -- BSTR to parse; ie 'redmond\bob:F'
|
|
// sDelim -- deliminator to find
|
|
//
|
|
// [out] int -- number of deliminators found in string
|
|
// Purpose: Return the number of deliminators found in a string. This is used
|
|
// by 'PutElement'
|
|
//-------------------------------------------------------------
|
|
int CIISSCO50::NumberOfDelims(CComBSTR& bString, CComBSTR bDelim)
|
|
{
|
|
|
|
// initialize variables
|
|
int iCount = 0;
|
|
int length;
|
|
|
|
|
|
// Convert the BSTR to a std:string
|
|
USES_CONVERSION;
|
|
std::string s = OLE2A(bString.m_str);
|
|
std::string sDelim = OLE2A(bDelim.m_str);
|
|
|
|
length = s.length();
|
|
|
|
// Loop through string looking for deliminator
|
|
for (size_t pos = s.find(sDelim)+1; pos < length; pos = s.find(sDelim, pos+2)+1)
|
|
{
|
|
// pos = 0 when it goes off end of string
|
|
if ( pos == 0 ) break;
|
|
iCount++;
|
|
|
|
}
|
|
|
|
// return
|
|
return iCount;
|
|
}
|
|
|
|
/* --------------------- XML Helper Methods ------------------------------- */
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: GetElementValueByAttribute
|
|
// Author: Russ Gibfried
|
|
// Params: [in] elementName -- element name to look for
|
|
// [out] pVal -- value of element
|
|
// Purpose: Return value of particular element in XML document
|
|
// <Property name="someName">someValue</Property>
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::GetElementValueByAttribute(CComPtr<IXMLDOMNode> pTopNode,CComBSTR elementName, CComBSTR attributeName, CComBSTR& pVal)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IXMLDOMNodeList> pNodeList; // List of nodes matching elementName
|
|
CComPtr<IXMLDOMNode> pNode; // individual node
|
|
CComPtr<IXMLDOMNamedNodeMap> pAttributeMap;
|
|
CComPtr<IXMLDOMNode> pXMLElement;
|
|
|
|
|
|
// Get a node list, ie, all <Property> tags
|
|
if (S_OK == (hr = pTopNode->selectNodes(elementName,&pNodeList)))
|
|
{
|
|
|
|
// Get the number of nodes and loop through them looking for
|
|
// specific Property found in attribute 'name='
|
|
long lLength;
|
|
pNodeList->get_length(&lLength);
|
|
for ( int i=0; i < lLength; i++)
|
|
{
|
|
// Get a node
|
|
hr = pNodeList->get_item(i,&pNode);
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
|
|
//Get 'name' attribute of this nodes <Property> tag
|
|
hr = pNode->get_attributes(&pAttributeMap);
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
|
|
BSTR bstrProperty = SysAllocString(L"");
|
|
|
|
hr = pAttributeMap->getNamedItem(L"name",&pXMLElement);
|
|
if (SUCCEEDED(hr)) hr = pXMLElement->get_text(&bstrProperty);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// If the property in attribute name is the same as passed in, then get value
|
|
if ( bstrProperty == attributeName.m_str)
|
|
{
|
|
// Setup a BSTR to get element value
|
|
BSTR bstrTemp = SysAllocString(L"");
|
|
hr = pXMLElement->get_text(&bstrTemp);
|
|
|
|
// Copy BSTR to CComBSTR and free it
|
|
if (SUCCEEDED(hr)) hr = pVal.CopyTo(&bstrTemp);
|
|
SysFreeString(bstrTemp);
|
|
i = lLength;
|
|
|
|
}
|
|
} // end if attribute
|
|
} // end if node
|
|
} //end if pNode
|
|
} // end for
|
|
|
|
}
|
|
else
|
|
{
|
|
// element name doesn't exists
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: GetInputAttr
|
|
// Author: Russ Gibfried
|
|
// Params: [in] pTopNode -- xml Node pointer
|
|
// AttributeName -- attribute name to look for
|
|
// elementName -- element name
|
|
// [out] pVal -- value of attribute
|
|
// Purpose: Select a tag based on its name (elementName) and
|
|
// Return the value of particular attribute in XML document
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::GetInputAttr(CComPtr<IXMLDOMNode> pTopNode, CComBSTR elementName, CComBSTR AttributeName, CComBSTR& pVal)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
CComPtr<IXMLDOMNamedNodeMap> pAttributeMap;
|
|
CComPtr<IXMLDOMNode> pNode;
|
|
CComPtr<IXMLDOMNode> pXMLElement;
|
|
|
|
|
|
|
|
if ( pTopNode != NULL )
|
|
{
|
|
// if elementName = "", then at current node
|
|
if ( elementName.Length() == 0 )
|
|
{
|
|
pNode = pTopNode;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
// Get the node of the element we are looking for ie, "./Website"
|
|
hr = pTopNode->selectSingleNode(elementName,&pNode);
|
|
}
|
|
|
|
// Get the attribute value
|
|
if (SUCCEEDED(hr) && pNode != NULL)
|
|
{
|
|
|
|
//Get 'name' attribute of this nodes <Property name=''> tag
|
|
hr = pNode->get_attributes(&pAttributeMap);
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
// Return the attributes value
|
|
hr = pAttributeMap->getNamedItem(AttributeName,&pXMLElement);
|
|
if (SUCCEEDED(hr)) hr = pXMLElement->get_text(&pVal);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( FAILED(hr) ) hr = E_SCO_IIS_XML_ATTRIBUTE_MISSING;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: GetInputParam
|
|
// Author: Russ Gibfried
|
|
// Params: [in] elementName -- element name to look for. ie IpAddress
|
|
// [out] pVal -- value of element ie. 10.2.1.10
|
|
// Purpose: Return value of particular element in XML document
|
|
// ex) <IpAddress>10.2.1.10</IpAddress>
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::GetInputParam(CComPtr<IXMLDOMNode> pNode,CComBSTR elementName,CComBSTR& pVal)
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
CComPtr<IXMLDOMNode> pXMLElement;
|
|
|
|
if ( pNode != NULL )
|
|
{
|
|
if (S_OK == (hr = pNode->selectSingleNode(elementName,&pXMLElement)))
|
|
{
|
|
pXMLElement->get_text(&pVal);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: PutElement
|
|
// Author: Russ Gibfried
|
|
// Params: [in] pNode -- xml node pointer
|
|
// elementName -- element name to look for
|
|
// [in] newVal -- new value of element
|
|
// Purpose: Return HRESULT
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::PutElement(CComPtr<IXMLDOMNode> pNode, CComBSTR elementName, CComBSTR newVal)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
CComPtr<IXMLDOMDocument> pDoc;
|
|
CComPtr<IXMLDOMNode> pNewNode;
|
|
CComPtr<IXMLDOMNode> pLastChild;
|
|
CComPtr<IXMLDOMNode> pTempNode;
|
|
|
|
if ( pNode != NULL )
|
|
{
|
|
|
|
// Find the Element 'elementName'
|
|
if (S_OK != (hr = pNode->selectSingleNode(elementName,&pNewNode)))
|
|
{
|
|
|
|
// Could not find element so create new node and add to DOM
|
|
hr = CoCreateInstance(
|
|
__uuidof(DOMDocument),
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
__uuidof(IXMLDOMDocument),
|
|
(LPVOID*)&pDoc);
|
|
|
|
// Get the node name from the element path. ie, './WebSite/ConfigPath' yields 'ConfigPath'
|
|
int iCount = NumberOfDelims(elementName, L"/");
|
|
CComBSTR bstrElement;
|
|
if ( SUCCEEDED(hr)) hr = ParseBSTR(elementName, L"/", iCount, 99, bstrElement);
|
|
|
|
// Create the new node
|
|
VARIANT vtTemp;
|
|
vtTemp.vt = VT_I2;
|
|
vtTemp.iVal = NODE_ELEMENT;
|
|
if ( SUCCEEDED(hr)) hr = pDoc->createNode(vtTemp,bstrElement,NULL, &pNewNode);
|
|
|
|
// Insert text in new node
|
|
if ( SUCCEEDED(hr)) hr= pNewNode->put_text(newVal.m_str);
|
|
|
|
// Get the last child node
|
|
if ( SUCCEEDED(hr)) hr = pNode->get_lastChild(&pLastChild);
|
|
|
|
// Append our new node to the end of the last child node
|
|
if ( SUCCEEDED(hr)) hr = pLastChild->appendChild(pNewNode,&pTempNode);
|
|
|
|
// Debug code to verify node built correctly.
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrDebug;
|
|
hr = pNode->get_xml(&bstrDebug);
|
|
ATLTRACE(_T("\t>>>PutElement: xml = : %ls\n"), bstrDebug.m_str);
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = pNewNode->put_text(newVal.m_str);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: AppendElement
|
|
// Author: Russ Gibfried
|
|
// Params: [in] pNode -- xml node pointer
|
|
// xmlString -- well formed XML fragment; ie <Property></Property>
|
|
// [out] pNewNode -- xml pointer to new node
|
|
// Purpose: Return HRESULT
|
|
// Appends a XML tag to the end of a given node.
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::AppendElement(CComPtr<IXMLDOMNode> pNode, CComBSTR xmlString,CComPtr<IXMLDOMNode>& pNewNode)
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
CComPtr<IXMLDOMDocument> pDoc;
|
|
CComPtr<IXMLDOMElement> pNewElement;
|
|
VARIANT_BOOL bSuccess = VARIANT_FALSE;
|
|
|
|
if ( pNode != NULL )
|
|
{
|
|
// Load string into XML Document
|
|
hr = CoCreateInstance(
|
|
__uuidof(DOMDocument),
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
__uuidof(IXMLDOMDocument),
|
|
(LPVOID*)&pDoc);
|
|
|
|
if (SUCCEEDED(hr)) hr = pDoc->loadXML(xmlString, &bSuccess);
|
|
if ( SUCCEEDED(hr) && bSuccess != VARIANT_FALSE)
|
|
{
|
|
// Get the document element
|
|
hr = pDoc->get_documentElement(&pNewElement);
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
// append new element to XML node passed in
|
|
hr = pNode->appendChild(pNewElement,&pNewNode);
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: GetNodeLength
|
|
// Author: Russ Gibfried
|
|
// Params: [in] pNode -- pointer to xml node
|
|
// elementName -- element name to look for
|
|
// [out] iLength -- number of elements matching that name
|
|
// Purpose: Return HRESULT
|
|
//-------------------------------------------------------------
|
|
HRESULT CIISSCO50::GetNodeLength(CComPtr<IXMLDOMNode> pTopNode, CComBSTR elementName, long *lLength)
|
|
{
|
|
|
|
// initialize variables
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IXMLDOMNodeList> pXMLNode;
|
|
long lTemp = 0;
|
|
lLength = &lTemp;
|
|
|
|
// Get a node list, ie, all <Property> tags
|
|
if (S_OK == (hr = pTopNode->selectNodes(elementName,&pXMLNode)))
|
|
{
|
|
pXMLNode->get_length(lLength);
|
|
}
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: IsPositiveInteger
|
|
// Author: Russ Gibfried
|
|
// Params: [in]
|
|
// bstrPort -- port number as a string
|
|
// [out] Boolean - True if the port is a positive integer
|
|
// Purpose: Function checks if the port or server number is a posivive integer
|
|
// and less than 20,000
|
|
//
|
|
//-------------------------------------------------------------
|
|
BOOL CIISSCO50::IsPositiveInteger(CComBSTR bstrPort)
|
|
{
|
|
BOOL bInteger = false;
|
|
long iPort = 0;
|
|
|
|
CComVariant var(bstrPort.m_str);
|
|
|
|
// We're
|
|
var.ChangeType(VT_I4);
|
|
iPort = var.lVal;
|
|
|
|
if ( iPort > 0 && iPort <= IIS_SERVER_MAX)
|
|
bInteger = true;
|
|
|
|
|
|
return bInteger;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Method: StringCompare
|
|
// Author: Russ Gibfried
|
|
// Params: [in] bString1 -- BSTR string1
|
|
// bString2 -- BSTR string2
|
|
//
|
|
// [out] Boolean - True/False if string1 and string2 equal
|
|
// Purpose: Compares to strings and returns 'true' if they are equal.
|
|
//-------------------------------------------------------------
|
|
BOOL CIISSCO50::StringCompare(CComBSTR bstrString1, CComBSTR bstrString2)
|
|
{
|
|
|
|
// initialize variables
|
|
bool bEqual = false;
|
|
|
|
bEqual = (wcscmp(bstrString1.m_str, bstrString2.m_str) == 0) ? true : false;
|
|
|
|
return bEqual;
|
|
|
|
}
|
|
|