Windows2003-3790/inetsrv/iis/svcs/smtp/adminsso/vdir.cpp
2020-09-30 16:53:55 +02:00

665 lines
16 KiB
C++

// vdir.cpp : Implementation of CsmtpadmApp and DLL registration.
#include "stdafx.h"
#include <listmacr.h>
#include "IADM.h"
#include "imd.h"
#include "inetcom.h"
#include "smtpadm.h"
#include "vdir.h"
#include "oleutil.h"
#include "metafact.h"
#include "metautil.h"
#include "smtpcmn.h"
#include "smtpprop.h"
// Must define THIS_FILE_* macros to use SmtpCreateException()
#define THIS_FILE_HELP_CONTEXT 0
#define THIS_FILE_PROG_ID _T("Smtpadm.VirtualDirectory.1")
#define THIS_FILE_IID IID_ISmtpAdminVirtualDirectory
typedef struct _VDIR_ENTRY {
TCHAR szName[METADATA_MAX_NAME_LEN+2];
TCHAR szDirectory[MAX_PATH + UNLEN + 3];
TCHAR szUser[UNLEN+1];
TCHAR szPassword[PWLEN+1];
DWORD dwAccess;
DWORD dwSslAccess;
BOOL fLogAccess;
LIST_ENTRY list;
} VDIR_ENTRY, * PVDIR_ENTRY;
/////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP CSmtpAdminVirtualDirectory::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_ISmtpAdminVirtualDirectory,
};
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
CSmtpAdminVirtualDirectory::CSmtpAdminVirtualDirectory () :
m_dwServiceInstance ( 0 ),
m_lCount ( 0 )
// CComBSTR's are initialized to NULL by default.
{
m_dwAccess = MD_ACCESS_READ | MD_ACCESS_WRITE;
m_dwSslAccess = 0;
InitializeListHead( &m_list );
}
CSmtpAdminVirtualDirectory::~CSmtpAdminVirtualDirectory ()
{
Clear();
// All CComBSTR's are freed automatically.
}
void CSmtpAdminVirtualDirectory::Clear()
{
m_lCount = 0;
m_fEnumerateCalled = FALSE;
m_strName.Empty();
m_strDirectory.Empty();
m_strUser.Empty();
m_strPassword.Empty();
m_dwAccess = MD_ACCESS_READ | MD_ACCESS_WRITE;
m_dwSslAccess = 0;
// release memory
PLIST_ENTRY pHead;
PLIST_ENTRY pEntry;
PLIST_ENTRY pTemp;
PVDIR_ENTRY pCurVDir=NULL;
for( pHead=&m_list, pEntry=pHead->Flink; pEntry!=pHead; )
{
pTemp = pEntry;
pEntry= pEntry->Flink;
pCurVDir = CONTAINING_RECORD(pTemp, VDIR_ENTRY, list);
RemoveEntryList( pTemp );
delete pCurVDir;
}
_ASSERT( IsListEmpty(&m_list) );
}
//////////////////////////////////////////////////////////////////////
// Properties:
//////////////////////////////////////////////////////////////////////
// Which service to configure:
STDMETHODIMP CSmtpAdminVirtualDirectory::get_Server ( BSTR * pstrServer )
{
return StdPropertyGet ( m_strServer, pstrServer );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::put_Server ( BSTR strServer )
{
return StdPropertyPutServerName ( &m_strServer, strServer );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::get_ServiceInstance ( long * plServiceInstance )
{
return StdPropertyGet ( m_dwServiceInstance, plServiceInstance );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::put_ServiceInstance ( long lServiceInstance )
{
return StdPropertyPut ( (long *) &m_dwServiceInstance, lServiceInstance );
}
// enumeration
STDMETHODIMP CSmtpAdminVirtualDirectory::get_Count ( long * plCount )
{
return StdPropertyGet ( m_lCount, plCount );
}
// VirtualDirectory property
STDMETHODIMP CSmtpAdminVirtualDirectory::get_VirtualName ( BSTR * pstrName )
{
return StdPropertyGet ( m_strName, pstrName );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::put_VirtualName ( BSTR strName )
{
return StdPropertyPut ( &m_strName, strName );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::get_Directory ( BSTR * pstrPath )
{
return StdPropertyGet ( m_strDirectory, pstrPath );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::put_Directory ( BSTR strPath )
{
return StdPropertyPut ( &m_strDirectory, strPath );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::get_User ( BSTR * pstrUserName )
{
return StdPropertyGet ( m_strUser, pstrUserName );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::put_User ( BSTR strUserName )
{
return StdPropertyPut ( &m_strUser, strUserName );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::get_Password ( BSTR * pstrPassword )
{
return StdPropertyGet ( m_strPassword, pstrPassword );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::put_Password ( BSTR strPassword )
{
return StdPropertyPut ( &m_strPassword, strPassword );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::get_LogAccess( BOOL* pfLogAccess )
{
return StdPropertyGet ( m_fLogAccess, pfLogAccess );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::put_LogAccess( BOOL fLogAccess )
{
return StdPropertyPut ( &m_fLogAccess, fLogAccess );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::get_AccessPermission( long* plAccessPermission )
{
return StdPropertyGet ( m_dwAccess, plAccessPermission );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::put_AccessPermission( long lAccessPermission )
{
return StdPropertyPut ( &m_dwAccess, lAccessPermission );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::get_SslAccessPermission( long* plSslAccessPermission )
{
return StdPropertyGet ( m_dwSslAccess, plSslAccessPermission );
}
STDMETHODIMP CSmtpAdminVirtualDirectory::put_SslAccessPermission( long lSslAccessPermission )
{
return StdPropertyPut ( &m_dwSslAccess, lSslAccessPermission );
}
//////////////////////////////////////////////////////////////////////
// Methods:
//////////////////////////////////////////////////////////////////////
// get /set property for current vdir
STDMETHODIMP CSmtpAdminVirtualDirectory::GetHomeDirectory( )
{
TraceFunctEnter ( "CSmtpAdminVirtualDirectory::GetHomeDirectory" );
m_strName.Empty();
m_strName = _T("");
return Get();
}
STDMETHODIMP CSmtpAdminVirtualDirectory::SetHomeDirectory( )
{
TraceFunctEnter ( "CSmtpAdminVirtualDirectory::SetHomeDirectory" );
m_strName.Empty();
m_strName = _T("");
return Set();
}
STDMETHODIMP CSmtpAdminVirtualDirectory::Create ( )
{
TraceFunctEnter ( "CSmtpAdminVirtualDirectory::Create" );
HRESULT hr = NOERROR;
CComPtr<IMSAdminBase> pmetabase;
TCHAR szPath[METADATA_MAX_NAME_LEN+2] = {0};
if( !m_strName || !m_strDirectory )
{
FatalTrace ( (LPARAM) this, "No virtual directory to create!" );
hr = E_POINTER;
return hr;
}
hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pmetabase );
if ( FAILED(hr) ) {
return SmtpCreateExceptionFromHresult(hr);
}
CMetabaseKey hMB( pmetabase );
GetMDRootPath( szPath, m_dwServiceInstance );
hr = hMB.Open( szPath, METADATA_PERMISSION_WRITE );
BAIL_ON_FAILURE(hr);
hr = hMB.CreateChild(m_strName);
BAIL_ON_FAILURE(hr);
if( !SetVRootPropertyToMetabase( &hMB, m_strName, m_strDirectory, m_strUser, m_strPassword, m_dwAccess, m_dwSslAccess, m_fLogAccess) )
{
hr = SmtpCreateExceptionFromWin32Error( GetLastError() );
goto Exit;
}
hr = hMB.Save();
BAIL_ON_FAILURE(hr);
Exit:
if( FAILED(hr) )
{
hr = SmtpCreateExceptionFromHresult(hr);
}
TraceFunctLeave ();
return hr;
}
STDMETHODIMP CSmtpAdminVirtualDirectory::Delete ( )
{
TraceFunctEnter ( "CSmtpAdminVirtualDirectory::Delete" );
HRESULT hr = NOERROR;
CComPtr<IMSAdminBase> pmetabase;
TCHAR szPath[METADATA_MAX_NAME_LEN+2] = {0};
if ( !m_strName ) {
FatalTrace ( (LPARAM) this, "Bad dir name to delete" );
return E_POINTER;
}
hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pmetabase );
if ( FAILED(hr) ) {
return hr;
}
GetMDRootPath( szPath, m_dwServiceInstance );
CMetabaseKey hMB( pmetabase );
hr = hMB.Open( szPath, METADATA_PERMISSION_WRITE);
BAIL_ON_FAILURE(hr);
hr = hMB.DestroyChild(m_strName);
BAIL_ON_FAILURE(hr);
hr = hMB.Save();
BAIL_ON_FAILURE(hr);
Exit:
if( FAILED(hr) )
{
hr = SmtpCreateExceptionFromHresult(hr);
}
TraceFunctLeave ();
return hr;
}
// get /set property for current vdir
STDMETHODIMP CSmtpAdminVirtualDirectory::Get( )
{
TraceFunctEnter ( "CSmtpAdminVirtualDirectory::Get" );
HRESULT hr = NOERROR;
CComPtr<IMSAdminBase> pmetabase;
TCHAR szPath[METADATA_MAX_NAME_LEN+2] = {0};
TCHAR szDirectory[MAX_PATH + UNLEN + 3] = {0};
TCHAR szUser[UNLEN+1] = {0};
TCHAR szPassword[PWLEN+1] = {0};
// zero out
m_strDirectory = (BSTR)NULL;
m_strUser = (BSTR)NULL;
m_strPassword = (BSTR)NULL;
if( !m_strName )
{
FatalTrace ( (LPARAM) this, "No virtual directory to create!" );
hr = E_POINTER;
return hr;
}
hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pmetabase );
if ( FAILED(hr) ) {
return hr;
}
CMetabaseKey hMB( pmetabase );
GetMDVDirPath( szPath, m_dwServiceInstance, m_strName );
hr = hMB.Open( szPath );
if( FAILED(hr) )
{
hr = SmtpCreateExceptionFromWin32Error( GetLastError() );
goto Exit;
}
if( !GetVRootPropertyFromMetabase( &hMB, _T(""), szDirectory, szUser, szPassword, &m_dwAccess, &m_dwSslAccess, &m_fLogAccess) )
{
hr = SmtpCreateExceptionFromWin32Error( GetLastError() );
goto Exit;
}
m_strDirectory = szDirectory;
m_strUser = szUser;
m_strPassword = szPassword;
Exit:
TraceFunctLeave ();
return hr;
}
STDMETHODIMP CSmtpAdminVirtualDirectory::Set( )
{
TraceFunctEnter ( "CSmtpAdminVirtualDirectory::Set" );
HRESULT hr = NOERROR;
CComPtr<IMSAdminBase> pmetabase;
TCHAR szPath[METADATA_MAX_NAME_LEN+2] = {0};
if( !m_strName || !m_strDirectory )
{
ErrorTrace ( (LPARAM) this, "No virtual directory to create!" );
hr = E_POINTER;
return hr;
}
hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pmetabase );
if ( FAILED(hr) ) {
return hr;
}
CMetabaseKey hMB( pmetabase );
GetMDVDirPath( szPath, m_dwServiceInstance, m_strName );
hr = hMB.Open( szPath,METADATA_PERMISSION_WRITE );
BAIL_ON_FAILURE(hr);
if( !SetVRootPropertyToMetabase( &hMB, _T(""), m_strDirectory, m_strUser, m_strPassword, m_dwAccess, m_dwSslAccess, m_fLogAccess) )
{
hr = SmtpCreateExceptionFromWin32Error( GetLastError() );
return hr;
}
hr = hMB.Save();
Exit:
if( FAILED(hr) )
{
hr = SmtpCreateExceptionFromHresult(hr);
}
TraceFunctLeave ();
return hr;
}
STDMETHODIMP CSmtpAdminVirtualDirectory::Enumerate( )
{
TraceFunctEnter ( "CSmtpAdminVirtualDirectory::Enumerate" );
HRESULT hr = NOERROR;
CComPtr<IMSAdminBase> pmetabase;
TCHAR szPath[METADATA_MAX_NAME_LEN+2] = {0};
DWORD dwAccess;
DWORD dwSslAccess;
BOOL fLogAccess;
TCHAR szName[METADATA_MAX_NAME_LEN+2];
TCHAR szDirectory[MAX_PATH + UNLEN + 3];
TCHAR szUser[UNLEN+1];
TCHAR szPassword[PWLEN+1];
INT i;
PVDIR_ENTRY pCurVDir=NULL;
hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pmetabase );
if ( FAILED(hr) ) {
return hr;;
}
GetMDRootPath( szPath, m_dwServiceInstance );
CMetabaseKey hMB( pmetabase );
hr = hMB.Open( szPath );
if( FAILED(hr) )
{
hr = SmtpCreateExceptionFromHresult( hr );
goto Exit;
}
Clear(); // reset state, m_lCount = 0
i = 0;
while( SUCCEEDED( hMB.EnumObjects(_T(""), szName, i ++) ) )
{
if ( !GetVRootPropertyFromMetabase( &hMB, szName, szDirectory, szUser, szPassword, &dwAccess, &dwSslAccess, &fLogAccess) )
{
continue;
}
pCurVDir = new VDIR_ENTRY;
if( !pCurVDir )
{
hr = E_OUTOFMEMORY;
goto Exit;
}
lstrcpy( pCurVDir->szName, szName);
lstrcpy( pCurVDir->szDirectory, szDirectory);
lstrcpy( pCurVDir->szUser, szUser);
lstrcpy( pCurVDir->szPassword, szPassword);
pCurVDir-> dwAccess = dwAccess;
pCurVDir-> dwSslAccess = dwSslAccess;
pCurVDir-> fLogAccess = fLogAccess;
InsertHeadList( &m_list, &(pCurVDir->list) );
m_lCount ++;
}
// _ASSERT( GetLastError() == ERROR_NO_MORE_ITEMS );
m_fEnumerateCalled = TRUE;
Exit:
TraceFunctLeave ();
return hr;
}
STDMETHODIMP CSmtpAdminVirtualDirectory::GetNth ( long lIndex )
{
TraceFunctEnter ( "CSmtpAdminVirtualDirectory::GetNth" );
if( lIndex < 0 || lIndex >= m_lCount )
{
TraceFunctLeave ();
return SmtpCreateException ( IDS_SMTPEXCEPTION_INVALID_INDEX );
}
PLIST_ENTRY pEntry;
PVDIR_ENTRY pVdir;
INT i;
if( !m_fEnumerateCalled )
{
TraceFunctLeave ();
return SmtpCreateException ( IDS_SMTPEXCEPTION_INVALID_INDEX );
}
// zero out
m_strName = (BSTR)NULL;
m_strDirectory = (BSTR)NULL;
m_strUser = (BSTR)NULL;
m_strPassword = (BSTR)NULL;
pEntry = &m_list;
for( i=0; i<=lIndex; i++ )
{
pEntry=pEntry->Flink;
_ASSERT( pEntry != & m_list);
if( pEntry == & m_list )
{
TraceFunctLeave ();
return SmtpCreateException ( IDS_SMTPEXCEPTION_INVALID_INDEX );
}
}
pVdir = CONTAINING_RECORD(pEntry, VDIR_ENTRY, list);
// automatically changed to UNICODE
m_strName = pVdir->szName;
m_strDirectory = pVdir->szDirectory;
m_strUser = pVdir->szUser;
m_strPassword = pVdir->szPassword;
TraceFunctLeave ();
return NOERROR;
}
BOOL CSmtpAdminVirtualDirectory::GetVRootPropertyFromMetabase(
CMetabaseKey* hMB,
const TCHAR* szName,
TCHAR* szDirectory,
TCHAR* szUser,
TCHAR* szPassword,
DWORD* pdwAccess,
DWORD* pdwSslAccess,
BOOL* pfLogAccess
)
{
DWORD cb;
DWORD dwDontLog = DEFAULT_LOG_TYPE;
HRESULT hr = NOERROR;
TraceFunctEnter ( "CSmtpAdminVirtualDirectory::GetVRootPropertyFromMetabase" );
cb = (MAX_PATH + UNLEN + 3) * sizeof(TCHAR);
hr = hMB->GetString( szName, MD_VR_PATH, szDirectory,cb,0 );
if( FAILED(hr) )
{
szDirectory[0] = _T('\0');
}
StdGetMetabaseProp( hMB, MD_ACCESS_PERM, MD_ACCESS_READ | MD_ACCESS_WRITE,
pdwAccess, szName );
StdGetMetabaseProp( hMB, MD_SSL_ACCESS_PERM, 0,
pdwSslAccess, szName );
StdGetMetabaseProp( hMB, MD_DONT_LOG, DEFAULT_LOG_TYPE,
&dwDontLog, szName );
*pfLogAccess = !dwDontLog;
cb = sizeof(TCHAR) * (UNLEN+1);
hr = hMB->GetString(szName,MD_VR_USERNAME,szUser,cb);
if( FAILED(hr) )
{
szUser[0] = _T('\0');
}
cb = sizeof(TCHAR) * (PWLEN+1);
if ( (szUser[0] != _T('\0')) &&
(szDirectory[0] == _T('\\')) &&
(szDirectory[1] == _T('\\')) )
{
hr = hMB->GetString(szName,MD_VR_PASSWORD,szPassword,cb,METADATA_NO_ATTRIBUTES);
if( FAILED(hr) )
{
DebugTrace( (LPARAM)this, "Error %d reading path from %s\n", GetLastError(), szName);
szPassword[0] = _T('\0');
}
}
return TRUE;
}
BOOL CSmtpAdminVirtualDirectory::SetVRootPropertyToMetabase(
CMetabaseKey* hMB,
const TCHAR* szName,
const TCHAR* szDirectory,
const TCHAR* szUser,
const TCHAR* szPassword,
DWORD dwAccess,
DWORD dwSslAccess,
BOOL fLogAccess
)
{
DWORD dwDontLog = fLogAccess ? 0 : 1;
HRESULT hr = NOERROR;
hr = hMB->SetString( szName,MD_VR_PATH, szDirectory );
BAIL_ON_FAILURE(hr);
hr = hMB->SetDword( szName, MD_DONT_LOG, dwDontLog);
BAIL_ON_FAILURE(hr);
hr = hMB->SetDword( szName, MD_ACCESS_PERM, dwAccess );
BAIL_ON_FAILURE(hr);
hr = hMB->SetDword( szName, MD_SSL_ACCESS_PERM, dwSslAccess);
BAIL_ON_FAILURE(hr);
if( szUser[0] )
{
hr = hMB->SetString( szName, MD_VR_USERNAME, szUser);
}
if( szPassword[0] )
{
hr = hMB->SetString( szName, MD_VR_PASSWORD, szPassword, METADATA_INHERIT | METADATA_SECURE );
}
Exit:
if( FAILED(hr) )
{
SetLastError(hr);
return FALSE;
}
return TRUE;
}