|
|
// binding.cpp : Implementation of CServerBinding & CServerBindings.
#include "stdafx.h"
#include "smtpadm.h"
#include "cmultisz.h"
#include "binding.h"
#include "oleutil.h"
#include "smtpcmn.h"
HRESULT CBinding::SetProperties ( BSTR strIpAddress, long dwTcpPort, long dwSslPort ) { _ASSERT ( IS_VALID_STRING ( strIpAddress ) );
m_strIpAddress = strIpAddress; m_dwTcpPort = dwTcpPort; m_dwSslPort = dwSslPort;
if ( !m_strIpAddress ) { return E_OUTOFMEMORY; }
return NOERROR; }
// Must define THIS_FILE_* macros to use SmtpCreateException()
#define THIS_FILE_HELP_CONTEXT 0
#define THIS_FILE_PROG_ID _T("Smtpadm.VirtualServer.1")
#define THIS_FILE_IID IID_IServerBinding
/////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP CServerBinding::InterfaceSupportsErrorInfo(REFIID riid) { static const IID* arr[] = { &IID_IServerBinding, };
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++) { if (InlineIsEqualGUID(*arr[i],riid)) return S_OK; } return S_FALSE; }
CServerBinding::CServerBinding () // CComBSTR's are initialized to NULL by default.
{ }
CServerBinding::~CServerBinding () { // All CComBSTR's are freed automatically.
}
//////////////////////////////////////////////////////////////////////
// Properties:
//////////////////////////////////////////////////////////////////////
STDMETHODIMP CServerBinding::get_IpAddress ( BSTR * pstrIpAddress ) { return StdPropertyGet ( m_binding.m_strIpAddress, pstrIpAddress ); }
STDMETHODIMP CServerBinding::put_IpAddress ( BSTR strIpAddress ) { return StdPropertyPut ( &m_binding.m_strIpAddress, strIpAddress ); }
STDMETHODIMP CServerBinding::get_TcpPort ( long * pdwTcpPort ) { return StdPropertyGet ( m_binding.m_dwTcpPort, pdwTcpPort ); }
STDMETHODIMP CServerBinding::put_TcpPort ( long dwTcpPort ) { return StdPropertyPut ( &m_binding.m_dwTcpPort, dwTcpPort ); }
STDMETHODIMP CServerBinding::get_SslPort ( long * plSslPort ) { return StdPropertyGet ( m_binding.m_dwSslPort, plSslPort ); }
STDMETHODIMP CServerBinding::put_SslPort ( long lSslPort ) { return StdPropertyPut ( &m_binding.m_dwSslPort, lSslPort ); }
//
// Must define THIS_FILE_* macros to use SmtpCreateException()
//
#undef THIS_FILE_HELP_CONTEXT
#undef THIS_FILE_PROG_ID
#undef THIS_FILE_IID
#define THIS_FILE_HELP_CONTEXT 0
#define THIS_FILE_PROG_ID _T("smtpadm.VirtualServer.1")
#define THIS_FILE_IID IID_IServerBindings
/////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP CServerBindings::InterfaceSupportsErrorInfo(REFIID riid) { static const IID* arr[] = { &IID_IServerBindings, };
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++) { if (InlineIsEqualGUID(*arr[i],riid)) return S_OK; } return S_FALSE; }
CServerBindings::CServerBindings () : m_dwCount ( 0 ), m_rgBindings ( NULL ) // CComBSTR's are initialized to NULL by default.
{ }
CServerBindings::~CServerBindings () { // All CComBSTR's are freed automatically.
delete [] m_rgBindings; }
//////////////////////////////////////////////////////////////////////
// Properties:
//////////////////////////////////////////////////////////////////////
STDMETHODIMP CServerBindings::get_Count ( long * pdwCount ) { return StdPropertyGet ( m_dwCount, pdwCount ); }
//////////////////////////////////////////////////////////////////////
// Methods:
//////////////////////////////////////////////////////////////////////
STDMETHODIMP CServerBindings::Item ( long index, IServerBinding ** ppBinding ) { TraceFunctEnter ( "CServerBindings::Item" );
_ASSERT ( IS_VALID_OUT_PARAM ( ppBinding ) );
*ppBinding = NULL;
HRESULT hr = NOERROR; CComObject<CServerBinding> * pBinding = NULL;
if ( index < 0 || index >= m_dwCount ) { hr = SmtpCreateException ( IDS_SMTPEXCEPTION_INVALID_INDEX ); goto Exit; }
hr = CComObject<CServerBinding>::CreateInstance ( &pBinding ); if ( FAILED(hr) ) { goto Exit; }
_ASSERT ( pBinding ); hr = pBinding->SetProperties ( m_rgBindings[index] ); if ( FAILED(hr) ) { goto Exit; }
hr = pBinding->QueryInterface ( IID_IServerBinding, (void **) ppBinding ); _ASSERT ( SUCCEEDED(hr) );
Exit: if ( FAILED(hr) && hr != DISP_E_EXCEPTION ) { hr = SmtpCreateExceptionFromHresult ( hr ); }
if ( FAILED(hr) ) { delete pBinding; }
TraceFunctLeave (); return hr; }
STDMETHODIMP CServerBindings::ItemDispatch ( long index, IDispatch ** ppDispatch ) { HRESULT hr; CComPtr<IServerBinding> pBinding;
hr = Item ( index, &pBinding ); BAIL_ON_FAILURE ( hr );
hr = pBinding->QueryInterface ( IID_IDispatch, (void **) ppDispatch ); BAIL_ON_FAILURE ( hr );
Exit: return hr; }
STDMETHODIMP CServerBindings::Add ( BSTR strIpAddress, long dwTcpPort, long dwSslPort ) { TraceFunctEnter ( "CServerBindings::Add" );
_ASSERT ( IS_VALID_STRING ( strIpAddress ) );
HRESULT hr = NOERROR; CBinding * rgNewBindings = NULL; long i;
//
// Validate the new binding:
//
//
// See if we can merge this binding with an existing one:
//
if ( dwTcpPort == 0 || dwSslPort == 0 ) { for ( i = 0; i < m_dwCount; i++ ) {
if ( (dwTcpPort == 0 && m_rgBindings[i].m_dwSslPort == 0) || (dwSslPort == 0 && m_rgBindings[i].m_dwTcpPort == 0) ) {
if ( lstrcmpi ( m_rgBindings[i].m_strIpAddress, strIpAddress ) == 0 ) {
if ( m_rgBindings[i].m_dwSslPort == 0 ) { m_rgBindings[i].m_dwSslPort = dwSslPort; } else { m_rgBindings[i].m_dwTcpPort = dwTcpPort; } hr = NOERROR; goto Exit; } } } }
// Allocate the new binding array:
rgNewBindings = new CBinding [ m_dwCount + 1 ]; if ( !rgNewBindings ) { hr = E_OUTOFMEMORY; goto Exit; }
// Copy the old bindings to the new array:
for ( i = 0; i < m_dwCount; i++ ) { hr = rgNewBindings[i].SetProperties ( m_rgBindings[i] ); if ( FAILED (hr) ) { goto Exit; } }
// Add the new binding to the end of the array:
hr = rgNewBindings[m_dwCount].SetProperties ( strIpAddress, dwTcpPort, dwSslPort ); if ( FAILED(hr) ) { goto Exit; }
_ASSERT ( SUCCEEDED(hr) ); delete [] m_rgBindings; m_rgBindings = rgNewBindings; rgNewBindings = NULL; m_dwCount++;
Exit: if (FAILED(hr) && rgNewBindings) delete [] rgNewBindings;
TraceFunctLeave (); return hr; }
STDMETHODIMP CServerBindings::ChangeBinding ( long index, IServerBinding * pBinding ) { TraceFunctEnter ( "CServerBindings::ChangeBinding" );
HRESULT hr = NOERROR;
CComBSTR strIpAddress; long dwTcpPort; long dwSslPort;
if ( index < 0 || index >= m_dwCount ) { hr = SmtpCreateException ( IDS_SMTPEXCEPTION_INVALID_INDEX ); goto Exit; }
hr = pBinding->get_IpAddress ( &strIpAddress ); if ( FAILED(hr) ) { goto Exit; }
hr = pBinding->get_TcpPort ( &dwTcpPort ); if ( FAILED(hr) ) { goto Exit; }
hr = pBinding->get_SslPort ( &dwSslPort ); if ( FAILED(hr) ) { goto Exit; }
hr = m_rgBindings[index].SetProperties ( strIpAddress, dwTcpPort, dwSslPort ); if ( FAILED(hr) ) { goto Exit; }
Exit: TraceFunctLeave (); return hr; }
STDMETHODIMP CServerBindings::ChangeBindingDispatch ( long index, IDispatch * pDispatch ) { HRESULT hr; CComPtr<IServerBinding> pBinding;
hr = pDispatch->QueryInterface ( IID_IServerBinding, (void **) &pBinding ); BAIL_ON_FAILURE ( hr );
hr = ChangeBinding ( index, pBinding ); BAIL_ON_FAILURE ( hr );
Exit: return hr; }
STDMETHODIMP CServerBindings::Remove ( long index ) { TraceFunctEnter ( "CServerBindings::Remove" );
HRESULT hr = NOERROR; CBinding temp; long cPositionsToSlide;
if ( index < 0 || index >= m_dwCount ) { hr = SmtpCreateException ( IDS_SMTPEXCEPTION_INVALID_INDEX ); goto Exit; }
// Slide the array down by one position:
_ASSERT ( m_rgBindings );
cPositionsToSlide = (m_dwCount - 1) - index;
_ASSERT ( cPositionsToSlide < m_dwCount );
if ( cPositionsToSlide > 0 ) { // Save the deleted binding in temp:
CopyMemory ( &temp, &m_rgBindings[index], sizeof ( CBinding ) );
// Move the array down one:
MoveMemory ( &m_rgBindings[index], &m_rgBindings[index + 1], sizeof ( CBinding ) * cPositionsToSlide );
// Put the deleted binding on the end (so it gets destructed):
CopyMemory ( &m_rgBindings[m_dwCount - 1], &temp, sizeof ( CBinding ) );
// Zero out the temp binding:
ZeroMemory ( &temp, sizeof ( CBinding ) ); }
m_dwCount--;
Exit: TraceFunctLeave (); return hr; }
STDMETHODIMP CServerBindings::Clear ( ) { delete [] m_rgBindings; m_rgBindings = NULL; m_dwCount = 0;
return NOERROR; }
//////////////////////////////////////////////////////////////////////
//
// Useful routines to go from IServerBindings to
// Metabase data types.
//
//////////////////////////////////////////////////////////////////////
static DWORD CountBindingChars ( LPCWSTR strIpAddress, DWORD dwPort ) { _ASSERT ( IS_VALID_STRING ( strIpAddress ) );
DWORD cchResult = 0; WCHAR wszPort [256];
wsprintf ( wszPort, _T("%u"), dwPort );
cchResult += lstrlen ( strIpAddress ); // <IPADDRESS>
cchResult += 1; // :
cchResult += lstrlen ( wszPort ); // <PORT>
cchResult += 1; // :
// cchResult += lstrlen ( strPathHeader ); // <PATHHEADER>
cchResult += 1; // For the terminating NULL
return cchResult; }
static void ToBindingString ( LPCWSTR strIpAddress, DWORD dwPort, LPWSTR wszBinding ) { _ASSERT ( IS_VALID_STRING ( strIpAddress ) ); _ASSERT ( dwPort != 0 );
_ASSERT ( !IsBadWritePtr ( wszBinding, CountBindingChars ( strIpAddress, dwPort ) ) );
wsprintf ( wszBinding, _T("%s:%u:"), strIpAddress, dwPort ); }
static HRESULT FromBindingString ( LPCWSTR wszBinding, LPWSTR wszIpAddressOut, DWORD * pdwPort ) { HRESULT hr = NOERROR;
LPWSTR pchFirstColon; LPWSTR pchSecondColon;
WCHAR wszIpAddress [ 256 ]; WCHAR wszPort [ 256 ]; long dwPort;
LPWSTR pchColon;
wszIpAddress[0] = NULL; wszPort[0] = NULL;
pchFirstColon = wcschr ( wszBinding, _T(':') ); if ( pchFirstColon ) { pchSecondColon = wcschr ( pchFirstColon + 1, _T(':') ); }
if ( !pchFirstColon || !pchSecondColon ) { hr = E_FAIL; goto Exit; }
lstrcpyn ( wszIpAddress, wszBinding, 250 ); lstrcpyn ( wszPort, pchFirstColon + 1, 250 );
// Get the Port:
dwPort = _wtoi ( wszPort );
// Cutoff the IpAddress at the colon:
pchColon = wcschr ( wszIpAddress, _T(':') ); if ( pchColon ) { *pchColon = NULL; }
lstrcpy ( wszIpAddressOut, wszIpAddress ); *pdwPort = dwPort;
Exit: return hr; }
HRESULT MDBindingsToIBindings ( CMultiSz * pmsz, BOOL fTcpBindings, IServerBindings * pBindings ) { HRESULT hr = NOERROR; DWORD cBindings; DWORD i; LPCWSTR pchCurrent; CBinding binding;
cBindings = pmsz->Count ();
for ( i = 0, pchCurrent = *pmsz; i < cBindings; i++, pchCurrent += lstrlen ( pchCurrent ) + 1 ) {
WCHAR wszIpAddress[512]; DWORD dwPort;
hr = FromBindingString ( pchCurrent, wszIpAddress, &dwPort ); if ( FAILED(hr) ) { // Skip bad binding strings:
hr = NOERROR; continue; }
if ( fTcpBindings ) { hr = pBindings->Add ( wszIpAddress, dwPort, 0 ); } else { hr = pBindings->Add ( wszIpAddress, 0, dwPort ); } BAIL_ON_FAILURE(hr); }
Exit: return hr; }
HRESULT IBindingsToMDBindings ( IServerBindings * pBindings, BOOL fTcpBindings, CMultiSz * pmsz ) { HRESULT hr = NOERROR; long cBindings; long i; DWORD cbCount = 0; LPWSTR wszBindings = NULL;
// Count the characters of the regular bindings list:
cbCount = 0; pBindings->get_Count ( &cBindings );
for ( i = 0; i < cBindings; i++ ) { CComPtr<IServerBinding> pBinding; CComBSTR strIpAddress; long lTcpPort; long lSslPort;
hr = pBindings->Item ( i, &pBinding ); BAIL_ON_FAILURE(hr);
pBinding->get_IpAddress ( &strIpAddress ); pBinding->get_TcpPort ( &lTcpPort ); pBinding->get_SslPort ( &lSslPort );
if ( fTcpBindings ) { if ( lTcpPort != 0 ) { cbCount += CountBindingChars ( strIpAddress, lTcpPort ); } } else { if ( lSslPort != 0 ) { cbCount += CountBindingChars ( strIpAddress, lSslPort ); } } }
if ( cbCount == 0 ) { cbCount = 2; wszBindings = new WCHAR [ cbCount ];
if ( !wszBindings ) { hr = E_OUTOFMEMORY; goto Exit; }
wszBindings[0] = NULL; wszBindings[1] = NULL; } else { cbCount++; // For double null terminator
wszBindings = new WCHAR [ cbCount ]; if ( !wszBindings ) { BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY); }
LPWSTR pchCurrent = wszBindings;
for ( i = 0; i < cBindings; i++ ) { CComPtr<IServerBinding> pBinding; CComBSTR strIpAddress; long lTcpPort; long lSslPort;
hr = pBindings->Item ( i, &pBinding ); BAIL_ON_FAILURE(hr);
pBinding->get_IpAddress ( &strIpAddress ); pBinding->get_TcpPort ( &lTcpPort ); pBinding->get_SslPort ( &lSslPort );
if ( fTcpBindings ) { if ( lTcpPort != 0 ) { ToBindingString ( strIpAddress, lTcpPort, pchCurrent ); pchCurrent += lstrlen ( pchCurrent ) + 1; } } else { if ( lSslPort != 0 ) { ToBindingString ( strIpAddress, lSslPort, pchCurrent ); pchCurrent += lstrlen ( pchCurrent ) + 1; } } }
*pchCurrent = NULL; }
_ASSERT ( wszBindings[cbCount - 1] == NULL ); _ASSERT ( wszBindings[cbCount - 2] == NULL );
pmsz->Attach ( wszBindings );
Exit: return hr; }
#if 0
DWORD CBinding::SizeInChars ( ) { DWORD cchResult = 0; WCHAR wszTcpPort [256];
wsprintf ( wszTcpPort, _T("%d"), m_dwTcpPort );
cchResult += lstrlen ( m_strIpAddress ); // <IPADDRESS>
cchResult += 1; // :
cchResult += lstrlen ( wszTcpPort ); // <TCPPORT>
cchResult += 1; // :
// cchResult += lstrlen ( m_strPathHeader ); // <PATHHEADER>
return cchResult; }
void CBinding::ToString ( LPWSTR wszBinding ) { wsprintf ( wszBinding, _T("%s:%d:"), m_strIpAddress, m_dwTcpPort ); }
HRESULT CBinding::FromString ( LPCWSTR wszBinding ) { HRESULT hr = NOERROR;
LPWSTR pchFirstColon; LPWSTR pchSecondColon;
WCHAR wszIpAddress [ 256 ]; WCHAR wszTcpPort [ 256 ]; long dwTcpPort;
LPWSTR pchColon;
wszIpAddress[0] = NULL; wszTcpPort[0] = NULL;
pchFirstColon = wcschr ( wszBinding, _T(':') ); if ( pchFirstColon ) { pchSecondColon = wcschr ( pchFirstColon + 1, _T(':') ); }
if ( !pchFirstColon || !pchSecondColon ) { hr = E_FAIL; goto Exit; }
lstrcpyn ( wszIpAddress, wszBinding, 250 ); lstrcpyn ( wszTcpPort, pchFirstColon + 1, 250 );
// Get the TcpPort:
dwTcpPort = _wtoi ( wszTcpPort );
// Cutoff the IpAddress at the colon:
pchColon = wcschr ( wszIpAddress, _T(':') ); if ( pchColon ) { *pchColon = NULL; }
m_strIpAddress = wszIpAddress; m_dwTcpPort = dwTcpPort;
if ( !m_strIpAddress ) { hr = E_OUTOFMEMORY; goto Exit; }
Exit: return hr; }
HRESULT CServerBindings::FromMultiSz ( CMultiSz * pmsz ) { HRESULT hr; DWORD cBindings; DWORD i; LPCWSTR pchCurrent; CBinding binding;
hr = Clear (); _ASSERT ( SUCCEEDED(hr) );
cBindings = pmsz->Count ();
for ( i = 0, pchCurrent = *pmsz; i < cBindings; i++, pchCurrent += lstrlen ( pchCurrent ) + 1 ) {
hr = binding.FromString ( pchCurrent ); if ( FAILED(hr) ) { if ( hr == E_FAIL ) { // Skip the bad binding strings.
continue; } else { goto Exit; } }
hr = Add ( binding.m_strIpAddress, binding.m_dwTcpPort ); if ( FAILED(hr) ) { goto Exit; } }
Exit: return hr; }
HRESULT CServerBindings::ToMultiSz ( CMultiSz * pmsz ) { HRESULT hr = NOERROR; DWORD cchSize; long i; LPWSTR wszBindings; LPWSTR pchCurrent;
// Special case - the empty binding list:
if ( m_dwCount == 0 ) { cchSize = 2; wszBindings = new WCHAR [ cchSize ];
if ( !wszBindings ) { hr = E_OUTOFMEMORY; goto Exit; }
wszBindings[0] = NULL; wszBindings[1] = NULL; } else {
cchSize = 0;
for ( i = 0; i < m_dwCount; i++ ) { cchSize += m_rgBindings[i].SizeInChars ( ) + 1; } // Add the size of the final terminator:
cchSize += 1;
wszBindings = new WCHAR [ cchSize ]; if ( !wszBindings ) { hr = E_OUTOFMEMORY; goto Exit; }
for ( i = 0, pchCurrent = wszBindings; i < m_dwCount; i++ ) {
m_rgBindings[i].ToString ( pchCurrent ); pchCurrent += lstrlen ( pchCurrent ) + 1; }
// Add the final NULL terminator:
*pchCurrent = NULL; }
_ASSERT ( wszBindings[cchSize - 1] == NULL ); _ASSERT ( wszBindings[cchSize - 2] == NULL );
pmsz->Attach ( wszBindings );
_ASSERT ( pmsz->Count () == (DWORD) m_dwCount );
Exit: return hr; }
#endif
|