Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2430 lines
56 KiB

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1997
//
// File: cgenobj.cxx
//
// Contents: Microsoft ADs IIS Provider Generic Object
//
//
// History: 28-Feb-97 SophiaC Created.
//
//----------------------------------------------------------------------------
#include "iis.hxx"
#pragma hdrstop
// Class CIISGenObject
DEFINE_IDispatch_ExtMgr_Implementation(CIISGenObject)
DEFINE_IADs_Implementation(CIISGenObject)
CIISGenObject::CIISGenObject():
_pExtMgr(NULL),
_pPropertyCache(NULL),
_pszServerName(NULL),
_pszMetaBasePath(NULL),
_pAdminBase(NULL),
_pSchema(NULL),
_pDispMgr(NULL)
{
VariantInit(&_vFilter);
ENLIST_TRACKING(CIISGenObject);
}
HRESULT
CIISGenObject::CreateGenericObject(
BSTR Parent,
BSTR CommonName,
BSTR ClassName,
CCredentials& Credentials,
DWORD dwObjectState,
REFIID riid,
void **ppvObj
)
{
CIISGenObject FAR * pGenObject = NULL;
CADsExtMgr FAR * pExtensionMgr = NULL;
HRESULT hr = S_OK;
LPWSTR pszClassName = ClassName;
hr = AllocateGenObject(ClassName, Credentials, &pGenObject);
BAIL_ON_FAILURE(hr);
hr = pGenObject->InitializeCoreObject(
Parent,
CommonName,
ClassName,
L"",
CLSID_IISGenObject,
dwObjectState
);
BAIL_ON_FAILURE(hr);
hr = pGenObject->CacheMetaDataPath();
BAIL_ON_FAILURE(hr);
hr = pGenObject->_pPropertyCache->InitializePropertyCache(
pGenObject->_pszServerName
);
BAIL_ON_FAILURE(hr);
//
// To maintain compatibility with IIS4 we want to fail when
// creating a new object if the metabase path already exists.
//
if( ADS_OBJECT_UNBOUND == pGenObject->_dwObjectState )
{
hr = ::MetaBaseDetectKey( pGenObject->_pAdminBase,
pGenObject->_pszMetaBasePath
);
if( SUCCEEDED(hr) )
{
hr = HRESULT_FROM_WIN32( ERROR_ALREADY_EXISTS );
}
else if( ERROR_PATH_NOT_FOUND == HRESULT_CODE(hr) )
{
hr = S_OK;
}
BAIL_ON_FAILURE(hr);
}
if ( !_wcsicmp(ClassName, L"IIsFtpServer") ||
!_wcsicmp(ClassName, L"IIsWebServer") ||
!_wcsicmp(ClassName, L"IIsNntpServer") ||
!_wcsicmp(ClassName, L"IIsSmtpServer") ||
!_wcsicmp(ClassName, L"IIsPop3Server") ||
!_wcsicmp(ClassName, L"IIsImapServer")
)
{
pszClassName = L"IIsServer";
}
else if ( !_wcsicmp(ClassName, L"IIsWebDirectory") ||
!_wcsicmp(ClassName, L"IIsWebVirtualDir"))
{
pszClassName = L"IIsApp";
}
hr = ADSILoadExtensionManager(
pszClassName,
(IADs *)pGenObject,
Credentials,
pGenObject->_pDispMgr,
&pExtensionMgr
);
BAIL_ON_FAILURE(hr);
pGenObject->_pExtMgr = pExtensionMgr;
hr = pGenObject->QueryInterface(riid, ppvObj);
BAIL_ON_FAILURE(hr);
pGenObject->Release();
RRETURN(hr);
error:
delete pGenObject;
RRETURN(hr);
}
CIISGenObject::~CIISGenObject( )
{
if (_pExtMgr)
{
delete _pExtMgr;
}
VariantClear(&_vFilter);
if (_pDispMgr)
{
delete _pDispMgr;
}
if (_pPropertyCache)
{
delete _pPropertyCache;
}
if (_pszServerName) {
FreeADsStr(_pszServerName);
}
if (_pszMetaBasePath){
FreeADsStr(_pszMetaBasePath);
}
}
STDMETHODIMP
CIISGenObject::QueryInterface(REFIID iid, LPVOID FAR* ppv)
{
if (ppv == NULL) {
RRETURN(E_POINTER);
}
if (IsEqualIID(iid, IID_IUnknown))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsContainer))
{
*ppv = (IADsContainer FAR *) this;
}
else if (IsEqualIID(iid, IID_IADs))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IISBaseObject))
{
*ppv = (IISBaseObject FAR *) this;
}
else if (IsEqualIID(iid, IID_IDispatch))
{
*ppv = (IADs FAR *) this;
}
else if (_pExtMgr)
{
RRETURN(_pExtMgr->QueryInterface(iid,ppv));
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
HRESULT
CIISGenObject::SetInfo()
{
HRESULT hr = S_OK;
COSERVERINFO csiName;
COSERVERINFO *pcsiParam = &csiName;
IClassFactory * pcsfFactory = NULL;
IIISApplicationAdmin * pAppAdmin = NULL;
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
// Check to see if we're creating an IIsApplicationPool
// If so, use the IISApplicationAdmin interface
if ( !_wcsicmp(_ADsClass, L"IIsApplicationPool"))
{
memset(pcsiParam, 0, sizeof(COSERVERINFO));
//
// special case to handle "localhost" to work-around ole32 bug
//
if (_pszServerName == NULL || _wcsicmp(_pszServerName,L"localhost") == 0) {
pcsiParam->pwszName = NULL;
}
else {
pcsiParam->pwszName = _pszServerName;
}
hr = CoGetClassObject(
CLSID_WamAdmin,
CLSCTX_SERVER,
pcsiParam,
IID_IClassFactory,
(void**) &pcsfFactory
);
BAIL_ON_FAILURE(hr);
hr = pcsfFactory->CreateInstance(
NULL,
IID_IIISApplicationAdmin,
(void **) &pAppAdmin
);
BAIL_ON_FAILURE(hr);
hr = pAppAdmin->CreateApplicationPool( _Name );
// Don't BAIL_ON_FAILURE here! Check the HR below first...
}
// Otherwise do the creation the old fashioned way
else {
hr = IISCreateObject();
}
//
// Since methods that we aggregate like IIsApp::AppCreate may
// persist our path in the metabase we don't want to fail just
// because the path exists. This is done to maintain backward
// compatibility with IIS4.
//
if( ERROR_ALREADY_EXISTS != HRESULT_CODE(hr) )
{
BAIL_ON_FAILURE(hr);
}
//
// If the create succeded, set the object type to bound
//
SetObjectState(ADS_OBJECT_BOUND);
}
hr = IISSetObject();
BAIL_ON_FAILURE(hr);
error:
if (pcsfFactory) {
pcsfFactory->Release();
}
if (pAppAdmin) {
pAppAdmin->Release();
}
RRETURN(hr);
}
HRESULT
CIISGenObject::IISSetObject()
{
HRESULT hr = S_OK;
METADATA_HANDLE hObjHandle = NULL;
PMETADATA_RECORD pMetaDataArray = NULL;
DWORD dwMDNumDataEntries = 0;
//
// Add SetObject functionality : sophiac
//
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
hr = E_ADS_OBJECT_UNBOUND;
BAIL_ON_FAILURE(hr);
}
hr = OpenAdminBaseKey(
_Credentials,
_pszServerName,
(LPWSTR) _pszMetaBasePath,
METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
hr = _pPropertyCache->IISMarshallProperties(
&pMetaDataArray,
&dwMDNumDataEntries
);
BAIL_ON_FAILURE(hr);
hr = MetaBaseSetAllData(
_pAdminBase,
hObjHandle,
L"",
(PMETADATA_RECORD)pMetaDataArray,
dwMDNumDataEntries
);
BAIL_ON_FAILURE(hr);
error:
if (pMetaDataArray) {
FreeMetaDataRecordArray(pMetaDataArray, dwMDNumDataEntries);
}
if (_pAdminBase && hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
RRETURN(hr);
}
HRESULT
CIISGenObject::IISCreateObject()
{
HRESULT hr = S_OK;
METADATA_HANDLE hObjHandle = NULL;
METADATA_RECORD mdrData;
WCHAR DataBuf[MAX_PATH];
WCHAR * PathBuf = (WCHAR *)AllocADsMem((DWORD) wcslen(_pszMetaBasePath)*sizeof(WCHAR) + 2);
WCHAR * pChild = NULL;
if (PathBuf == NULL)
{
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
wcscpy(PathBuf, _pszMetaBasePath);
WCHAR * q = NULL, * p = NULL;
do
{
hr = MetaBaseDetectKey(_pAdminBase, PathBuf);
// if failed, try parent path
if (FAILED(hr))
{
p = _tcsrchr(PathBuf, _T('/'));
if (p != NULL)
{
if (q != NULL)
*q = _T('/');
*p = 0;
pChild = p + 1;
}
else
{
BAIL_ON_FAILURE(hr);
}
}
else
{
break;
}
q = p;
} while (true);
hr = OpenAdminBaseKey(
_Credentials,
_pszServerName,
PathBuf,
METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
if (pChild != NULL)
{
hr = MetaBaseCreateObject(
_pAdminBase,
hObjHandle,
pChild
);
}
if( ERROR_ALREADY_EXISTS != HRESULT_CODE(hr) )
{
BAIL_ON_FAILURE(hr);
}
//
// Set KeyType
//
if (wcslen(_ADsClass) >= MAX_PATH)
{
BAIL_ON_FAILURE(E_ADS_BAD_PARAMETER);
}
wcscpy((LPWSTR)DataBuf, _ADsClass);
mdrData.dwMDIdentifier = MD_KEY_TYPE;
mdrData.dwMDDataType = STRING_METADATA;
mdrData.dwMDUserType = IIS_MD_UT_SERVER;
mdrData.dwMDAttributes = METADATA_NO_ATTRIBUTES;
mdrData.dwMDDataLen = (DWORD)(wcslen(DataBuf)+1)*2;
mdrData.pbMDData = (PBYTE)DataBuf;
hr = _pAdminBase->SetData(
hObjHandle,
pChild,
&mdrData);
BAIL_ON_FAILURE(hr);
error:
if (_pAdminBase && hObjHandle)
{
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
if (PathBuf != NULL)
{
FreeADsMem(PathBuf);
}
RRETURN(hr);
}
HRESULT
CIISGenObject::GetInfo()
{
_pPropertyCache->flushpropcache();
RRETURN(GetInfo(TRUE));
}
HRESULT
CIISGenObject::GetInfo(
BOOL fExplicit
)
{
HRESULT hr = S_OK;
METADATA_HANDLE hObjHandle = NULL;
DWORD dwMDAttributes = METADATA_INHERIT;
DWORD dwMDUserType = ALL_METADATA;
DWORD dwMDDataType = ALL_METADATA;
DWORD dwMDNumDataEntries;
DWORD dwMDDataSetNumber;
LPBYTE pBuffer = NULL;
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
hr = E_ADS_OBJECT_UNBOUND;
BAIL_ON_FAILURE(hr);
}
hr = OpenAdminBaseKey(
_Credentials,
_pszServerName,
_pszMetaBasePath,
METADATA_PERMISSION_READ,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
hr = MetaBaseGetAllData(
_pAdminBase,
hObjHandle,
L"",
dwMDAttributes,
dwMDUserType,
dwMDDataType,
&dwMDNumDataEntries,
&dwMDDataSetNumber,
(LPBYTE *)&pBuffer
);
BAIL_ON_FAILURE(hr);
hr = _pPropertyCache->IISUnMarshallProperties(
pBuffer,
pBuffer,
dwMDNumDataEntries,
fExplicit
);
BAIL_ON_FAILURE(hr);
error:
if (pBuffer) {
FreeADsMem(pBuffer);
}
if (_pAdminBase && hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
RRETURN(hr);
}
/* IADsContainer methods */
STDMETHODIMP
CIISGenObject::get_Count(long FAR* retval)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISGenObject::get_Filter(THIS_ VARIANT FAR* pVar)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISGenObject::put_Filter(THIS_ VARIANT Var)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISGenObject::put_Hints(THIS_ VARIANT Var)
{
RRETURN( E_NOTIMPL);
}
STDMETHODIMP
CIISGenObject::get_Hints(THIS_ VARIANT FAR* pVar)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISGenObject::GetObject(
BSTR ClassName,
BSTR RelativeName,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
hr = ::RelativeGetObject(
_ADsPath,
ClassName,
RelativeName,
_Credentials,
ppObject,
FALSE
);
RRETURN(hr);
}
STDMETHODIMP
CIISGenObject::get__NewEnum(
THIS_ IUnknown * FAR* retval
)
{
HRESULT hr;
IUnknown FAR* punkEnum=NULL;
IEnumVARIANT * penum = NULL;
*retval = NULL;
hr = CIISGenObjectEnum::Create(
(CIISGenObjectEnum **)&penum,
_ADsPath,
_vFilter,
_Credentials
);
BAIL_ON_FAILURE(hr);
hr = penum->QueryInterface(
IID_IUnknown,
(VOID FAR* FAR*)retval
);
BAIL_ON_FAILURE(hr);
if (penum) {
penum->Release();
}
RRETURN(NOERROR);
error:
if (penum) {
delete penum;
}
RRETURN(hr);
}
inline
HRESULT
ValidateRelativePath(
IN LPCWSTR wszRelativePath
)
/*++
Routine Description:
Determine if a relative path is valid. This is really just to check
assumptions that are made about the relative path.
It doesn't do much now, but might be expanded and moved to a common
location if necessary.
Arguments:
IN wszRelativePath : a relative ads path
Return Value:
E_ADS_BAD_PATHNAME if the path is not valid
--*/
{
HRESULT hr = E_ADS_BAD_PATHNAME;
if( wszRelativePath && *wszRelativePath != L'/' )
{
hr = S_OK;
}
RRETURN(hr);
}
STDMETHODIMP
CIISGenObject::Create(
THIS_ BSTR ClassName,
BSTR RelativeName,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
IADs * pADs = NULL;
BOOL bRelativeNameExtended = FALSE;
LPWSTR pwszParentClass = NULL;
LPWSTR pwszParentADsPath = NULL;
LPWSTR pwszRelativeName = NULL;
DWORD i = 0;
//
// Validate if this class really exists in the schema
// and validate that this object can be created in this
// container
//
hr = _pSchema->ValidateClassName(ClassName);
BAIL_ON_FAILURE(hr);
//
// Handle case where RelativeName may be an extended path,
// such as foo/bar/baz.
//
hr = ValidateRelativePath( RelativeName );
BAIL_ON_FAILURE(hr);
bRelativeNameExtended = ( wcschr( RelativeName, L'/' ) != NULL );
if( bRelativeNameExtended )
{
pwszRelativeName = wcsrchr( RelativeName, L'/' ) + 1;
hr = ResolveExtendedChildPath( RelativeName,
&pwszParentADsPath,
&pwszParentClass );
BAIL_ON_FAILURE(hr);
}
else
{
pwszParentClass = _ADsClass;
pwszParentADsPath = _ADsPath;
pwszRelativeName = RelativeName;
}
//
// validate name --> can't have ',' in the name
//
while (RelativeName[i] != L'\0' && RelativeName[i] != L',')
i++;
if (RelativeName[i] != L'\0' || i >= METADATA_MAX_NAME_LEN) {
hr = E_ADS_BAD_PARAMETER;
BAIL_ON_FAILURE(hr);
}
hr = _pSchema->ValidateContainedClassName(pwszParentClass, ClassName);
BAIL_ON_FAILURE(hr);
hr = CIISGenObject::CreateGenericObject(
pwszParentADsPath,
pwszRelativeName,
ClassName,
_Credentials,
ADS_OBJECT_UNBOUND,
IID_IADs,
(void **)&pADs
);
BAIL_ON_FAILURE(hr);
hr = pADs->QueryInterface(
IID_IDispatch,
(void **)ppObject
);
BAIL_ON_FAILURE(hr);
error:
if (pADs) {
pADs->Release();
}
if( bRelativeNameExtended )
{
ADsFreeString( pwszParentClass );
ADsFreeString( pwszParentADsPath );
}
RRETURN(hr);
}
STDMETHODIMP
CIISGenObject::Delete(
THIS_ BSTR bstrClassName,
BSTR bstrRelativeName
)
{
HRESULT hr = S_OK;
METADATA_HANDLE hObjHandle = NULL;
COSERVERINFO csiName;
COSERVERINFO *pcsiParam = &csiName;
IClassFactory * pcsfFactory = NULL;
IIISApplicationAdmin * pAppAdmin = NULL;
//
// Get Server and Path name
//
hr = CacheMetaDataPath();
BAIL_ON_FAILURE(hr);
// Check to see if we're deleting an IIsApplicationPool
// If so, use the IISApplicationAdmin interface
if ( !_wcsicmp(bstrClassName, L"IIsApplicationPool"))
{
memset(pcsiParam, 0, sizeof(COSERVERINFO));
//
// special case to handle "localhost" to work-around ole32 bug
//
if (_pszServerName == NULL || _wcsicmp(_pszServerName,L"localhost") == 0) {
pcsiParam->pwszName = NULL;
}
else {
pcsiParam->pwszName = _pszServerName;
}
hr = CoGetClassObject(
CLSID_WamAdmin,
CLSCTX_SERVER,
pcsiParam,
IID_IClassFactory,
(void**) &pcsfFactory
);
BAIL_ON_FAILURE(hr);
hr = pcsfFactory->CreateInstance(
NULL,
IID_IIISApplicationAdmin,
(void **) &pAppAdmin
);
BAIL_ON_FAILURE(hr);
hr = pAppAdmin->DeleteApplicationPool( bstrRelativeName );
BAIL_ON_FAILURE(hr);
}
// Otherwise do the delete the old fashioned way
else {
hr = OpenAdminBaseKey(
_Credentials,
_pszServerName,
_pszMetaBasePath,
METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
//
// Pass in full path
//
hr = MetaBaseDeleteObject(
_pAdminBase,
hObjHandle,
(LPWSTR)bstrRelativeName
);
BAIL_ON_FAILURE(hr);
}
error:
if (pcsfFactory) {
pcsfFactory->Release();
}
if (pAppAdmin) {
pAppAdmin->Release();
}
if (_pAdminBase && hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
RRETURN(hr);
}
STDMETHODIMP
CIISGenObject::CopyHere(
THIS_ BSTR SourceName,
BSTR NewName,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
IUnknown *pUnk = NULL;
METADATA_HANDLE hObjHandle = NULL;
LPWSTR pszIISPathName = NULL;
IADs *pADs = NULL;
BSTR bstrClassName = NULL;
LPWSTR pszPath = NULL;
IWamAdmin2 *pWamAdmin = NULL;
LPWSTR pszIISNewName = NULL;
bool bIsW3 = false;
bIsW3 = CheckIsW3(_ADsPath);
if (bIsW3)
{
hr = InitWamAdmin(_pszServerName, &pWamAdmin);
BAIL_ON_FAILURE(hr);
}
//
// open common path node
//
hr = BuildIISPathFromADsPath(
_ADsPath,
&pszIISPathName
);
BAIL_ON_FAILURE(hr);
hr = OpenAdminBaseKey(
_Credentials,
_pszServerName,
pszIISPathName,
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
//
// Do Copy operation
//
hr = MetaBaseCopyObject(
_pAdminBase,
hObjHandle,
(LPWSTR)SourceName,
hObjHandle,
(LPWSTR)NewName
);
BAIL_ON_FAILURE(hr);
if (hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
hObjHandle = NULL;
}
if (pszIISPathName) {
DWORD dwLen;
dwLen = (DWORD)(wcslen(pszIISPathName) + wcslen(NewName)) + 2;
pszIISNewName = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
if (!pszIISNewName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
wcscpy(pszIISNewName, pszIISPathName);
if (NewName) {
wcscat(pszIISNewName, L"/");
wcscat(pszIISNewName, (LPWSTR)NewName);
}
}
if (bIsW3 && pWamAdmin)
{
hr = pWamAdmin->AppRecover((LPWSTR) pszIISNewName, TRUE);
BAIL_ON_FAILURE(hr);
}
hr = get_CoreADsClass(&bstrClassName);
BAIL_ON_FAILURE(hr);
hr = CIISGenObject::CreateGenericObject(
_ADsPath,
NewName,
bstrClassName,
_Credentials,
ADS_OBJECT_BOUND,
IID_IADs,
(void **)&pADs
);
BAIL_ON_FAILURE(hr);
pszPath = ((CIISGenObject*)pADs)->ReturnMetaDataPath();
hr = pADs->QueryInterface(
IID_IDispatch,
(void **)ppObject
);
BAIL_ON_FAILURE(hr);
error:
if (_pAdminBase) {
if (hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
}
if (pWamAdmin) {
UninitWamAdmin(pWamAdmin);
}
if (bstrClassName) {
ADsFreeString(bstrClassName);
}
if (pszIISPathName) {
FreeADsStr(pszIISPathName);
}
if (pszIISNewName) {
FreeADsMem(pszIISNewName);
}
if (pADs){
pADs->Release();
}
RRETURN(hr);
}
bool
CIISGenObject::CheckIsW3(LPCWSTR pszPath)
{
// we should only return true if the second part of the path = 'W3SVC'
// IIS://localhost/W3SVC/1/blah
WCHAR* token = NULL;
WCHAR* pszWorker = NULL;
pszWorker = new WCHAR[(DWORD)wcslen(pszPath) + 1];
if (!pszWorker)
{
return false;
}
wcscpy(pszWorker, pszPath);
// get the first token
token = wcstok((WCHAR*)pszWorker, L"/");
// get the second token
token = wcstok(NULL, L"/");
token = wcstok(NULL, L"/");
if (token && !_wcsicmp(token, L"w3svc"))
{
if (pszWorker)
{
delete [] pszWorker;
}
return true;
}
if (pszWorker)
{
delete [] pszWorker;
}
return false;
}
STDMETHODIMP
CIISGenObject::MoveHere(
THIS_ BSTR SourceName,
BSTR NewName,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
IUnknown *pUnk = NULL;
METADATA_HANDLE hObjHandle = NULL;
LPWSTR pszIISPathName = NULL;
IADs *pADs = NULL;
BSTR bstrClassName = NULL;
LPWSTR pszPath = NULL;
IWamAdmin2 *pWamAdmin = NULL;
LPWSTR pszIISOldName = NULL;
LPWSTR pszIISNewName = NULL;
bool bIsW3 = false;
bIsW3 = CheckIsW3(_ADsPath);
if (bIsW3)
{
hr = InitWamAdmin(_pszServerName, &pWamAdmin);
BAIL_ON_FAILURE(hr);
}
//
// open common path node
//
hr = BuildIISPathFromADsPath(
_ADsPath,
&pszIISPathName
);
BAIL_ON_FAILURE(hr);
if (pszIISPathName) {
DWORD dwLen;
dwLen = (DWORD)(wcslen(pszIISPathName) + wcslen(SourceName)) + 2;
pszIISOldName = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
if (!pszIISOldName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
wcscpy(pszIISOldName, pszIISPathName);
if (NewName) {
wcscat(pszIISOldName, L"/");
wcscat(pszIISOldName, (LPWSTR)SourceName);
}
}
if (bIsW3 && pWamAdmin)
{
hr = pWamAdmin->AppDeleteRecoverable((LPWSTR) pszIISOldName, TRUE);
BAIL_ON_FAILURE(hr);
}
hr = OpenAdminBaseKey(
_Credentials,
_pszServerName,
pszIISPathName,
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
//
// Do Move operation
//
hr = MetaBaseMoveObject(
_pAdminBase,
hObjHandle,
(LPWSTR)SourceName,
hObjHandle,
(LPWSTR)NewName
);
BAIL_ON_FAILURE(hr);
if (hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
hObjHandle = NULL;
}
if (pszIISPathName) {
DWORD dwLen;
dwLen = (DWORD)(wcslen(pszIISPathName) + wcslen(NewName)) + 2;
pszIISNewName = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
if (!pszIISNewName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
wcscpy(pszIISNewName, pszIISPathName);
if (NewName) {
wcscat(pszIISNewName, L"/");
wcscat(pszIISNewName, (LPWSTR)NewName);
}
}
if (bIsW3 && pWamAdmin)
{
hr = pWamAdmin->AppRecover((LPWSTR) pszIISNewName, TRUE);
BAIL_ON_FAILURE(hr);
}
hr = get_CoreADsClass(&bstrClassName);
BAIL_ON_FAILURE(hr);
hr = CIISGenObject::CreateGenericObject(
_ADsPath,
NewName,
bstrClassName,
_Credentials,
ADS_OBJECT_BOUND,
IID_IADs,
(void **)&pADs
);
BAIL_ON_FAILURE(hr);
pszPath = ((CIISGenObject*)pADs)->ReturnMetaDataPath();
hr = pADs->QueryInterface(
IID_IDispatch,
(void **)ppObject
);
BAIL_ON_FAILURE(hr);
error:
if (_pAdminBase) {
if (hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
}
if (pWamAdmin) {
UninitWamAdmin(pWamAdmin);
}
if (bstrClassName) {
ADsFreeString(bstrClassName);
}
if (pszIISPathName) {
FreeADsStr(pszIISPathName);
}
if (pszIISOldName) {
FreeADsMem(pszIISOldName);
}
if (pszIISNewName) {
FreeADsMem(pszIISNewName);
}
if (pADs){
pADs->Release();
}
RRETURN(hr);
}
HRESULT
CIISGenObject::AllocateGenObject(
LPWSTR pszClassName,
CCredentials& Credentials,
CIISGenObject ** ppGenObject
)
{
CIISGenObject FAR * pGenObject = NULL;
CAggregatorDispMgr FAR * pDispMgr = NULL;
CPropertyCache FAR * pPropertyCache = NULL;
HRESULT hr = S_OK;
pGenObject = new CIISGenObject();
if (pGenObject == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
pDispMgr = new CAggregatorDispMgr;
if (pDispMgr == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADs,
(IADs *)pGenObject,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(LIBID_ADs,
IID_IADsContainer,
(IADsContainer *)pGenObject,
DISPID_NEWENUM
);
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_IISOle,
IID_IISBaseObject,
(IISBaseObject *)pGenObject,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
hr = CPropertyCache::createpropertycache(
(CCoreADsObject FAR *)pGenObject,
&pPropertyCache
);
BAIL_ON_FAILURE(hr);
pDispMgr->RegisterPropertyCache((IPropertyCache*)pPropertyCache);
pGenObject->_Credentials = Credentials;
pGenObject->_pPropertyCache = pPropertyCache;
pGenObject->_pDispMgr = pDispMgr;
*ppGenObject = pGenObject;
RRETURN(hr);
error:
if (pDispMgr)
{
delete pDispMgr;
}
if (pGenObject)
{
delete pGenObject;
}
RRETURN(hr);
}
/* INTRINSA suppress=null_pointers, uninitialized */
STDMETHODIMP
CIISGenObject::Get(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId;
DWORD dwSyntax;
DWORD dwNumValues = 0;
LPIISOBJECT pIISSrcObjects = NULL;
WCHAR wchName[MAX_PATH];
BSTR bstrClassName = NULL;
//
// check if property is a supported property
//
hr = get_CoreADsClass(&bstrClassName);
BAIL_ON_FAILURE(hr);
if (NULL == bstrClassName)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
hr = _pSchema->ValidateProperty(bstrClassName, bstrName);
BAIL_ON_FAILURE(hr);
//
// lookup ADSI IIS syntax Id
//
hr = _pSchema->LookupSyntaxID(bstrName, &dwSyntax);
BAIL_ON_FAILURE(hr);
//
// check if property is BITMASK type;
// if BITMASK type, get corresponding DWORD flag property
//
// check if property is RAW BINARY type;
// if RAW BINARY type, get corresponding NTACL flag property
//
if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY) {
hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
BAIL_ON_FAILURE(hr);
}
//
// retrieve data object from cache; if one exists
//
if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY)
{
hr = _pPropertyCache->getproperty(
wchName,
&dwSyntaxId,
&dwNumValues,
&pIISSrcObjects
);
}
else
{
hr = _pPropertyCache->getproperty(
bstrName,
&dwSyntaxId,
&dwNumValues,
&pIISSrcObjects
);
}
BAIL_ON_FAILURE(hr);
//
// reset it to its syntax id if BITMASK type
//
pIISSrcObjects->IISType = dwSyntax;
//
// translate the IIS objects to variants
//
//
// always return an array for multisz type
//
if (dwSyntax == IIS_SYNTAX_ID_BINARY)
{
hr = IISTypeToVarTypeCopy(
_pSchema,
bstrName,
pIISSrcObjects,
pvProp,
TRUE
);
}
else if (dwNumValues == 1 && dwSyntax != IIS_SYNTAX_ID_MULTISZ &&
dwSyntax != IIS_SYNTAX_ID_MIMEMAP ) {
hr = IISTypeToVarTypeCopy(
_pSchema,
bstrName,
pIISSrcObjects,
pvProp,
FALSE
);
}else {
hr = IISTypeToVarTypeCopyConstruct(
_pSchema,
bstrName,
pIISSrcObjects,
dwNumValues,
pvProp,
FALSE
);
}
BAIL_ON_FAILURE(hr);
error:
if (bstrClassName) {
ADsFreeString(bstrClassName);
}
if (pIISSrcObjects) {
IISTypeFreeIISObjects(
pIISSrcObjects,
dwNumValues
);
}
RRETURN(hr);
}
STDMETHODIMP
CIISGenObject::Put(
THIS_ BSTR bstrName,
VARIANT vProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId = 0;
DWORD dwIndex = 0;
LPIISOBJECT pIISDestObjects = NULL;
DWORD dwNumValues = 0;
VARIANT * pVarArray = NULL;
VARIANT * pvProp = NULL;
VARIANT vVar;
WCHAR wchName[MAX_PATH];
BSTR bstrClassName = NULL;
//
// check if property is a supported property
//
hr = get_CoreADsClass(&bstrClassName);
BAIL_ON_FAILURE(hr);
hr = _pSchema->ValidateProperty(bstrClassName, bstrName);
BAIL_ON_FAILURE(hr);
//
// lookup its syntax ID
//
hr = _pSchema->LookupSyntaxID( bstrName, &dwSyntaxId);
BAIL_ON_FAILURE(hr);
//
// Issue: How do we handle multi-valued support
//
VariantInit(&vVar);
hr = VariantCopyInd(&vVar, &vProp);
BAIL_ON_FAILURE(hr);
if ((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar)) {
hr = ConvertArrayToVariantArray(
vVar,
&pVarArray,
&dwNumValues
);
BAIL_ON_FAILURE(hr);
pvProp = pVarArray;
}
else {
dwNumValues = 1;
pvProp = &vVar;
}
//
// check if the variant maps to the syntax of this property
//
hr = VarTypeToIISTypeCopyConstruct(
dwSyntaxId,
pvProp,
dwNumValues,
&pIISDestObjects,
FALSE
);
BAIL_ON_FAILURE(hr);
//
// check if property is BITMASK type;
// if BITMASK type, get corresponding DWORD flag property
//
if (dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
VARIANT vGetProp;
DWORD dwMask;
DWORD dwFlagValue;
hr = _pSchema->LookupBitMask(bstrName, &dwMask);
BAIL_ON_FAILURE(hr);
//
// get its corresponding DWORD flag value
//
hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
BAIL_ON_FAILURE(hr);
VariantInit(&vGetProp);
hr = Get(wchName, &vGetProp);
BAIL_ON_FAILURE(hr);
dwFlagValue = V_I4(&vGetProp);
if (pIISDestObjects->IISValue.value_1.dwDWORD) {
dwFlagValue |= dwMask;
}
else {
dwFlagValue &= ~dwMask;
}
pIISDestObjects->IISValue.value_1.dwDWORD = dwFlagValue;
pIISDestObjects->IISType = IIS_SYNTAX_ID_DWORD;
bstrName = wchName;
}
if (dwSyntaxId == IIS_SYNTAX_ID_BINARY) {
hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
BAIL_ON_FAILURE(hr);
bstrName = wchName;
}
//
// Find this property in the cache
//
hr = _pPropertyCache->findproperty(
bstrName,
&dwIndex
);
//
// If this property does not exist in the
// cache, add this property into the cache.
//
if (FAILED(hr)) {
hr = _pPropertyCache->addproperty(
bstrName,
dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ?
IIS_SYNTAX_ID_DWORD : dwSyntaxId,
dwNumValues,
pIISDestObjects
);
//
// If the operation fails for some reason
// move on to the next property
//
BAIL_ON_FAILURE(hr);
}
//
// Now update the property in the cache
//
hr = _pPropertyCache->putproperty(
bstrName,
CACHE_PROPERTY_MODIFIED,
dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ?
IIS_SYNTAX_ID_DWORD : dwSyntaxId,
dwNumValues,
pIISDestObjects
);
BAIL_ON_FAILURE(hr);
error:
if (pIISDestObjects) {
IISTypeFreeIISObjects(
pIISDestObjects,
dwNumValues
);
}
if (bstrClassName) {
ADsFreeString(bstrClassName);
}
if (pVarArray) {
DWORD i = 0;
for (i = 0; i < dwNumValues; i++) {
VariantClear(pVarArray + i);
}
FreeADsMem(pVarArray);
}
VariantClear(&vVar);
RRETURN(hr);
}
STDMETHODIMP
CIISGenObject::PutEx(
THIS_ long lnControlCode,
BSTR bstrName,
VARIANT vProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId = 0;
DWORD dwIndex = 0;
LPIISOBJECT pIISDestObjects = NULL;
DWORD dwNumValues = 0;
DWORD dwFlags = 0;
VARIANT * pVarArray = NULL;
VARIANT * pvProp = NULL;
VARIANT vVar;
WCHAR wchName[MAX_PATH];
BSTR bstrClassName = NULL;
METADATA_HANDLE hObjHandle = NULL;
//
// check if property is a supported property
//
hr = get_CoreADsClass(&bstrClassName);
BAIL_ON_FAILURE(hr);
hr = _pSchema->ValidateProperty(bstrClassName, bstrName);
BAIL_ON_FAILURE(hr);
//
// lookup its syntax Id
//
hr = _pSchema->LookupSyntaxID( bstrName, &dwSyntaxId);
BAIL_ON_FAILURE(hr);
switch (lnControlCode) {
case ADS_PROPERTY_CLEAR:
dwFlags = CACHE_PROPERTY_CLEARED;
pIISDestObjects = NULL;
dwNumValues = 0;
break;
case ADS_PROPERTY_UPDATE:
dwFlags = CACHE_PROPERTY_MODIFIED;
//
// Now begin the rest of the processing
//
VariantInit(&vVar);
hr = VariantCopyInd(&vVar, &vProp);
BAIL_ON_FAILURE(hr);
if ((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar)) {
hr = ConvertArrayToVariantArray(
vVar,
&pVarArray,
&dwNumValues
);
BAIL_ON_FAILURE(hr);
pvProp = pVarArray;
}
else {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
VariantClear(&vVar);
//
// check if the variant maps to the syntax of this property
//
hr = VarTypeToIISTypeCopyConstruct(
dwSyntaxId,
pvProp,
dwNumValues,
&pIISDestObjects,
TRUE
);
BAIL_ON_FAILURE(hr);
break;
default:
RRETURN(hr = E_ADS_BAD_PARAMETER);
}
//
// check if property is BITMASK type;
// if BITMASK type, get corresponding DWORD flag property
//
if (dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
VARIANT vGetProp;
DWORD dwMask;
DWORD dwFlagValue;
hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
BAIL_ON_FAILURE(hr);
if (dwFlags != CACHE_PROPERTY_CLEARED) {
hr = _pSchema->LookupBitMask(bstrName, &dwMask);
BAIL_ON_FAILURE(hr);
//
// get its corresponding DWORD flag value
//
VariantInit(&vGetProp);
hr = Get(wchName, &vGetProp);
BAIL_ON_FAILURE(hr);
dwFlagValue = V_I4(&vGetProp);
if (pIISDestObjects->IISValue.value_1.dwDWORD) {
dwFlagValue |= dwMask;
}
else {
dwFlagValue &= ~dwMask;
}
pIISDestObjects->IISValue.value_1.dwDWORD = dwFlagValue;
pIISDestObjects->IISType = IIS_SYNTAX_ID_DWORD;
}
bstrName = wchName;
}
if (dwSyntaxId == IIS_SYNTAX_ID_BINARY) {
hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
BAIL_ON_FAILURE(hr);
bstrName = wchName;
}
//
// Find this property in the cache
//
hr = _pPropertyCache->findproperty(
bstrName,
&dwIndex
);
//
// If this property does not exist in the
// cache, add this property into the cache.
//
if (FAILED(hr)) {
hr = _pPropertyCache->addproperty(
bstrName,
dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ?
IIS_SYNTAX_ID_DWORD : dwSyntaxId,
dwNumValues,
pIISDestObjects
);
//
// If the operation fails for some reason
// move on to the next property
//
BAIL_ON_FAILURE(hr);
}
//
// Now update the property in the cache
//
hr = _pPropertyCache->putproperty(
bstrName,
dwFlags,
dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ?
IIS_SYNTAX_ID_DWORD : dwSyntaxId,
dwNumValues,
pIISDestObjects
);
BAIL_ON_FAILURE(hr);
if (dwFlags == CACHE_PROPERTY_CLEARED) {
DWORD dwMetaId;
hr = _pSchema->LookupMetaID(bstrName, &dwMetaId);
BAIL_ON_FAILURE(hr);
hr = InitServerInfo(_Credentials, _pszServerName, &_pAdminBase, &_pSchema);
BAIL_ON_FAILURE(hr);
hr = OpenAdminBaseKey(
_Credentials,
_pszServerName,
_pszMetaBasePath,
METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
hr = _pAdminBase->DeleteData(
hObjHandle,
(LPWSTR)L"",
dwMetaId,
ALL_METADATA
);
if (hr == MD_ERROR_DATA_NOT_FOUND) {
hr = S_OK;
}
}
error:
if (_pAdminBase && hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
if (bstrClassName) {
ADsFreeString(bstrClassName);
}
if (pIISDestObjects) {
IISTypeFreeIISObjects(
pIISDestObjects,
dwNumValues
);
}
if (pVarArray) {
DWORD i = 0;
for (i = 0; i < dwNumValues; i++) {
VariantClear(pVarArray + i);
}
FreeADsMem(pVarArray);
}
RRETURN(hr);
}
/* INTRINSA suppress=null_pointers, uninitialized */
STDMETHODIMP
CIISGenObject::GetEx(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId;
DWORD dwSyntax;
DWORD dwNumValues = 0;
LPIISOBJECT pIISSrcObjects = NULL;
WCHAR wchName[MAX_PATH];
BSTR bstrClassName = NULL;
//
// check if property is a supported property
//
hr = get_CoreADsClass(&bstrClassName);
BAIL_ON_FAILURE(hr);
if (NULL == bstrClassName)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
hr = _pSchema->ValidateProperty(bstrClassName, bstrName);
BAIL_ON_FAILURE(hr);
//
// lookup its syntax Id
//
hr = _pSchema->LookupSyntaxID(bstrName, &dwSyntax);
BAIL_ON_FAILURE(hr);
//
// check if property is BITMASK type;
// if BITMASK type, get corresponding DWORD flag property
//
// check if property is RAW BINARY type;
// if RAW BINARY type, get corresponding NTACL flag property
//
if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY) {
hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
BAIL_ON_FAILURE(hr);
}
//
// retrieve data object from cache; if one exists
//
if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY)
{
hr = _pPropertyCache->getproperty(
wchName,
&dwSyntaxId,
&dwNumValues,
&pIISSrcObjects
);
}
else
{
hr = _pPropertyCache->getproperty(
bstrName,
&dwSyntaxId,
&dwNumValues,
&pIISSrcObjects
);
}
BAIL_ON_FAILURE(hr);
//
// reset it to its syntax id if BITMASK type
//
pIISSrcObjects->IISType = dwSyntax;
//
// translate the IIS objects to variants
//
hr = IISTypeToVarTypeCopyConstruct(
_pSchema,
bstrName,
pIISSrcObjects,
dwNumValues,
pvProp,
TRUE
);
BAIL_ON_FAILURE(hr);
error:
if (bstrClassName) {
ADsFreeString(bstrClassName);
}
if (pIISSrcObjects) {
IISTypeFreeIISObjects(
pIISSrcObjects,
dwNumValues
);
}
RRETURN(hr);
}
HRESULT
CIISGenObject::CacheMetaDataPath()
{
HRESULT hr = E_FAIL;
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
CLexer Lexer(_ADsPath);
LPWSTR pszIISPathName = NULL;
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = ADsObject(&Lexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
_pszServerName = AllocADsStr(pObjectInfo->TreeName);
if (!_pszServerName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
hr = InitServerInfo(_Credentials, _pszServerName, &_pAdminBase, &_pSchema);
BAIL_ON_FAILURE(hr);
pszIISPathName = AllocADsStr(_ADsPath);
if (!pszIISPathName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
*pszIISPathName = L'\0';
hr = BuildIISPathFromADsPath(
pObjectInfo,
pszIISPathName
);
BAIL_ON_FAILURE(hr);
_pszMetaBasePath = AllocADsStr(pszIISPathName);
if (!_pszMetaBasePath) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
error:
if (pszIISPathName) {
FreeADsStr(pszIISPathName);
}
FreeObjectInfo(pObjectInfo);
RRETURN(hr);
}
STDMETHODIMP
CIISGenObject::GetDataPaths(
THIS_ BSTR bstrName,
THIS_ LONG lnAttribute,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
DWORD dwMetaId;
DWORD dwAttribute;
DWORD dwTemp;
METADATA_HANDLE hObjHandle = NULL;
LPBYTE pBuffer = NULL;
//
// check if property is a supported property
//
hr = _pSchema->LookupMetaID(bstrName, &dwMetaId);
BAIL_ON_FAILURE(hr);
hr = _pSchema->LookupMDFlags(dwMetaId, &dwAttribute, &dwTemp);
BAIL_ON_FAILURE(hr);
switch (lnAttribute) {
case IIS_ANY_PROPERTY:
break;
case IIS_INHERITABLE_ONLY:
if ((METADATA_INHERIT & dwAttribute) != METADATA_INHERIT) {
RRETURN(hr = MD_ERROR_DATA_NOT_FOUND);
}
break;
default :
RRETURN(hr = E_ADS_BAD_PARAMETER);
}
//
// Get Server and Path name
//
hr = CacheMetaDataPath();
BAIL_ON_FAILURE(hr);
hr = OpenAdminBaseKey(
_Credentials,
_pszServerName,
_pszMetaBasePath,
METADATA_PERMISSION_READ,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
hr = MetaBaseGetDataPaths(_pAdminBase,
hObjHandle,
dwMetaId,
(LPBYTE *)&pBuffer
);
BAIL_ON_FAILURE(hr);
hr = MakeVariantFromPathArray( (LPWSTR)_ADsPath, (LPWSTR)pBuffer, pvProp);
BAIL_ON_FAILURE(hr);
error:
if (pBuffer) {
FreeADsMem(pBuffer);
}
if (_pAdminBase && hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
RRETURN(hr);
}
STDMETHODIMP
CIISGenObject::GetPropertyAttribObj(
THIS_ BSTR bstrName,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
DWORD dwMetaId;
DWORD i = 0;
PROPERTYINFO *pPropertyInfo = NULL;
IISPropertyAttribute * pPropAttrib = NULL;
WCHAR wchName[MAX_PATH];
METADATA_HANDLE hObjHandle = NULL;
DWORD dwBufferSize = 0;
METADATA_RECORD mdrMDData;
LPBYTE pBuffer = NULL;
VARIANT vVar;
VariantInit(&vVar);
*ppObject = NULL;
//
// if passed in bstrName is a meta id, then convert it to property name
//
if (wcslen(bstrName) >= MAX_PATH) bstrName[MAX_PATH - 1] = L'\0';
wcscpy((LPWSTR)wchName, bstrName);
while (wchName[i] != L'\0' && wchName[i] >= L'0' &&
wchName[i] <= L'9') {
i++;
}
if (i == wcslen((LPWSTR)wchName)) {
dwMetaId = _wtoi((LPWSTR)wchName);
hr = _pSchema->ConvertID_To_PropName(dwMetaId, (LPWSTR)wchName);
BAIL_ON_FAILURE(hr);
}
else {
//
// check if property is a supported property
//
hr = _pSchema->LookupMetaID(bstrName, &dwMetaId);
BAIL_ON_FAILURE(hr);
}
hr = OpenAdminBaseKey(
_Credentials,
_pszServerName,
_pszMetaBasePath,
METADATA_PERMISSION_READ,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
MD_SET_DATA_RECORD(&mdrMDData,
dwMetaId,
METADATA_INHERIT | METADATA_ISINHERITED,
ALL_METADATA,
ALL_METADATA,
dwBufferSize,
pBuffer);
hr = _pAdminBase->GetData(
hObjHandle,
L"",
&mdrMDData,
&dwBufferSize
);
pBuffer = (LPBYTE) AllocADsMem(dwBufferSize);
mdrMDData.pbMDData = pBuffer;
mdrMDData.dwMDDataLen = dwBufferSize;
hr = _pAdminBase->GetData(
hObjHandle,
L"",
&mdrMDData,
&dwBufferSize
);
BAIL_ON_FAILURE(hr);
//
// get default value
//
pPropertyInfo = _pSchema->GetPropertyInfo(wchName);
ASSERT(pPropertyInfo != NULL);
if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_DWORD ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_MIMEMAP ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_IPSECLIST ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BINARY ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_NTACL) {
vVar.vt = VT_I4;
vVar.lVal = pPropertyInfo->dwDefault;
}
else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
vVar.vt = VT_BOOL;
vVar.boolVal = pPropertyInfo->dwDefault ? VARIANT_TRUE : VARIANT_FALSE;
}
else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_MULTISZ) {
LPWSTR pszStr = pPropertyInfo->szDefault;
hr = MakeVariantFromStringArray(NULL,
pszStr,
&vVar);
BAIL_ON_FAILURE(hr);
}
else {
vVar.vt = VT_BSTR;
hr = ADsAllocString( pPropertyInfo->szDefault, &(vVar.bstrVal));
BAIL_ON_FAILURE(hr);
}
hr = CPropertyAttribute::CreatePropertyAttribute(
IID_IISPropertyAttribute,
(VOID**)&pPropAttrib
);
BAIL_ON_FAILURE(hr);
hr = ((CPropertyAttribute*)pPropAttrib)->InitFromRawData(
(LPWSTR) wchName,
dwMetaId,
mdrMDData.dwMDUserType, // usertype
mdrMDData.dwMDAttributes, // attributes
&vVar
);
BAIL_ON_FAILURE(hr);
*ppObject = (IDispatch*)pPropAttrib;
error:
if (pBuffer) {
FreeADsMem(pBuffer);
}
if (hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
RRETURN(hr);
}
HRESULT
CIISGenObject::ResolveExtendedChildPath(
IN BSTR RelativeChildPath,
OUT BSTR *pParentPath,
OUT BSTR *pParentClass
)
/*++
Routine Description:
Helper method called from CIISGenObject::Create() finds the
metabase key that is most proximate to RelativeChildPath and
returns the ADS class for this key along with adjusted path
for the parent.
Arguments:
IN RelativeChildPath : An extended subpath, such as foo/bar
OUT pParentPath : Allocated with ADsAllocString
OUT pParentClass : Allocated with ADsAllocString
Return Value:
S_OK
S_FALSE : No path found in the metabase
--*/
{
ADsAssert( RelativeChildPath );
ADsAssert( pParentPath );
ADsAssert( pParentClass );
*pParentPath = NULL;
*pParentClass = NULL;
HRESULT hr = S_OK;
DWORD cbBuffSize;
LPWSTR pwszPathBuffer = NULL;
DWORD dwLen;
BOOL bFound;
WCHAR *pch = NULL;
WCHAR wszParentClassBuffer[MAX_PATH];
//
// Build buffer to hold the metabase and ads paths
//
cbBuffSize = (DWORD)((wcslen(_ADsPath) + wcslen(RelativeChildPath) + 2)
* sizeof(WCHAR));
pwszPathBuffer = (LPWSTR)AllocADsMem( cbBuffSize );
if( !pwszPathBuffer )
{
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
ZeroMemory( pwszPathBuffer, cbBuffSize );
//
// Build the metabase path for the child
//
if (wcslen(_pszMetaBasePath) > wcslen(_ADsPath))
{
BAIL_ON_FAILURE(E_ADS_BAD_PARAMETER);
}
wcscpy( pwszPathBuffer, _pszMetaBasePath );
dwLen = (DWORD)wcslen( pwszPathBuffer );
ADsAssert( dwLen );
if( pwszPathBuffer[dwLen - 1] != L'/' )
{
pwszPathBuffer[dwLen] = L'/';
}
wcscat( pwszPathBuffer, RelativeChildPath );
//
// Look for the closest path in the metabase to our child
//
bFound = FALSE;
pch = wcsrchr( pwszPathBuffer, L'/' );
if (pch != NULL)
*pch = 0;
while( !bFound && 0 != wcscmp( pwszPathBuffer, _pszMetaBasePath ) )
{
hr = MetaBaseDetectKey( _pAdminBase, pwszPathBuffer );
if( SUCCEEDED(hr) )
{
bFound = TRUE;
}
else if( ERROR_PATH_NOT_FOUND == HRESULT_CODE(hr) )
{
// Continue up the path buffer
pch = wcsrchr( pwszPathBuffer, L'/' );
if (pch != NULL)
*pch = 0;
hr = S_FALSE;
}
else
{
BAIL_ON_FAILURE( hr );
}
}
//
// Get pParentClass
//
if( bFound )
{
// Get the key type from the node
hr = MetaBaseGetADsClass( _pAdminBase,
pwszPathBuffer,
_pSchema,
wszParentClassBuffer,
MAX_PATH
);
BAIL_ON_FAILURE( hr );
}
else
{
// Use our own key type
if (wcslen(_ADsClass) >= MAX_PATH)
{
BAIL_ON_FAILURE(E_ADS_BAD_PARAMETER);
}
wcscpy( wszParentClassBuffer, _ADsClass );
}
hr = ADsAllocString( wszParentClassBuffer, pParentClass );
BAIL_ON_FAILURE( hr );
//
// Get pParentPath
//
wcscpy( pwszPathBuffer, _ADsPath );
wcscat( pwszPathBuffer, L"/" );
wcscat( pwszPathBuffer, RelativeChildPath );
pch = wcsrchr( pwszPathBuffer, L'/' );
if (pch != NULL)
*pch = 0;
hr = ADsAllocString( pwszPathBuffer, pParentPath );
BAIL_ON_FAILURE( hr );
error:
if( pwszPathBuffer )
{
FreeADsMem( pwszPathBuffer );
}
RRETURN( hr );
}