// domain.cpp : Implementation of CsmtpadmApp and DLL registration. #include "stdafx.h" #include "iadm.h" #include "iiscnfg.h" #include "smtpadm.h" #include "domain.h" #include "oleutil.h" #include "metautil.h" #include "listmacr.h" #include #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.Domain.1") #define THIS_FILE_IID IID_ISmtpAdminDomain #define UNASSIGNED_DOMAIN_ID ( DWORD( -1 ) ) ///////////////////////////////////////////////////////////////////////////// // // // Use a macro to define all the default methods // DECLARE_METHOD_IMPLEMENTATION_FOR_STANDARD_EXTENSION_INTERFACES(SmtpAdminDomain, CSmtpAdminDomain, IID_ISmtpAdminDomain) STDMETHODIMP CSmtpAdminDomain::InterfaceSupportsErrorInfo(REFIID riid) { static const IID* arr[] = { &IID_ISmtpAdminDomain, }; for (int i=0;iFlink; pEntry!=pHead; pEntry=pHead->Flink ) { pDomainEntry = CONTAINING_RECORD(pEntry, DomainEntry, list); RemoveEntryList(pEntry); delete pDomainEntry; } } // // IADs methods: // DECLARE_SIMPLE_IADS_IMPLEMENTATION(CSmtpAdminDomain,m_iadsImpl) ////////////////////////////////////////////////////////////////////// // Properties: ////////////////////////////////////////////////////////////////////// // enumeration STDMETHODIMP CSmtpAdminDomain::get_Count ( long * plCount ) { return StdPropertyGet ( m_lCount, plCount ); } // current Domain Properties: STDMETHODIMP CSmtpAdminDomain::get_DomainName ( BSTR * pstrDomainName ) { return StdPropertyGet ( m_strDomainName, pstrDomainName ); } STDMETHODIMP CSmtpAdminDomain::put_DomainName ( BSTR strDomainName ) { return StdPropertyPut ( &m_strDomainName, strDomainName ); } STDMETHODIMP CSmtpAdminDomain::get_ActionType( long * plActionType ) { return StdPropertyGet ( m_dwActionType, plActionType ); } STDMETHODIMP CSmtpAdminDomain::put_ActionType( long lActionType ) { return StdPropertyPut ( &m_dwActionType, lActionType ); } // drop IsDefault!! STDMETHODIMP CSmtpAdminDomain::get_IsDefault ( BOOL * pfIsDefault ) { *pfIsDefault = m_dwActionType == SMTP_DEFAULT; return NOERROR; } STDMETHODIMP CSmtpAdminDomain::put_IsDefault ( BOOL fIsDefault ) { return E_NOTIMPL; } STDMETHODIMP CSmtpAdminDomain::get_IsLocal ( BOOL * pfIsLocal ) { return E_NOTIMPL; } STDMETHODIMP CSmtpAdminDomain::put_IsLocal ( BOOL fIsLocal ) { return E_NOTIMPL; } // if local STDMETHODIMP CSmtpAdminDomain::get_LDAPServer ( BSTR * pstrLDAPServer ) { return E_NOTIMPL; //return StdPropertyGet ( m_strLDAPServer, pstrLDAPServer ); } STDMETHODIMP CSmtpAdminDomain::put_LDAPServer ( BSTR strLDAPServer ) { return E_NOTIMPL; //return StdPropertyPut ( &m_strLDAPServer, strLDAPServer ); } STDMETHODIMP CSmtpAdminDomain::get_Account ( BSTR * pstrAccount ) { return E_NOTIMPL; //return StdPropertyGet ( m_strAccount, pstrAccount ); } STDMETHODIMP CSmtpAdminDomain::put_Account ( BSTR strAccount ) { return E_NOTIMPL; //return StdPropertyPut ( &m_strAccount, strAccount ); } STDMETHODIMP CSmtpAdminDomain::get_Password ( BSTR * pstrPassword ) { return E_NOTIMPL; //return StdPropertyGet ( m_strPassword, pstrPassword ); } STDMETHODIMP CSmtpAdminDomain::put_Password ( BSTR strPassword ) { return E_NOTIMPL; //return StdPropertyPut ( &m_strPassword, strPassword ); } STDMETHODIMP CSmtpAdminDomain::get_LDAPContainer ( BSTR * pstrLDAPContainer ) { return E_NOTIMPL; //return StdPropertyGet ( m_strLDAPContainer, pstrLDAPContainer ); } STDMETHODIMP CSmtpAdminDomain::put_LDAPContainer ( BSTR strLDAPContainer ) { return E_NOTIMPL; //return StdPropertyPut ( &m_strLDAPContainer, strLDAPContainer ); } // if remote STDMETHODIMP CSmtpAdminDomain::get_UseSSL ( BOOL * pfUseSSL ) { return E_NOTIMPL; } STDMETHODIMP CSmtpAdminDomain::put_UseSSL ( BOOL fUseSSL ) { return E_NOTIMPL; } STDMETHODIMP CSmtpAdminDomain::get_EnableETRN ( BOOL * pfEnableETRN ) { return E_NOTIMPL; } STDMETHODIMP CSmtpAdminDomain::put_EnableETRN ( BOOL fEnableETRN ) { return E_NOTIMPL; } STDMETHODIMP CSmtpAdminDomain::get_DropDir ( BSTR * pstrDropDir ) { return StdPropertyGet ( m_strActionString, pstrDropDir ); } STDMETHODIMP CSmtpAdminDomain::put_DropDir ( BSTR strDropDir ) { return StdPropertyPut ( &m_strActionString, strDropDir ); } STDMETHODIMP CSmtpAdminDomain::get_RoutingDomain ( BSTR * pstrRoutingDomain ) { return StdPropertyGet ( m_strActionString, pstrRoutingDomain ); } STDMETHODIMP CSmtpAdminDomain::put_RoutingDomain ( BSTR strRoutingDomain ) { return StdPropertyPut ( &m_strActionString, strRoutingDomain ); } ////////////////////////////////////////////////////////////////////// // Methods: ////////////////////////////////////////////////////////////////////// STDMETHODIMP CSmtpAdminDomain::Default ( ) { TraceFunctEnter ( "CSmtpAdminDomain::Default" ); m_dwActionType = SMTP_DELIVER; m_fAllowEtrn = FALSE; m_dwDomainId = UNASSIGNED_DOMAIN_ID; m_strDomainName.Empty(); m_strActionString.Empty(); m_pCurrentDomainEntry = NULL; TraceFunctLeave (); return NOERROR; } STDMETHODIMP CSmtpAdminDomain::Add ( ) { TraceFunctEnter ( "CSmtpAdminDomain::Add" ); HRESULT hr = NOERROR; DomainEntry* pOldDef = NULL; DomainEntry* pNewDomain = new DomainEntry; if( !pNewDomain ) { ErrorTrace ( (LPARAM) this, "Out of memory" ); hr = E_OUTOFMEMORY; goto Exit; } hr = GetFromMetabase(); if( FAILED(hr) ) { goto Exit; } lstrcpyW( pNewDomain-> m_strDomainName, (LPCWSTR)m_strDomainName ); lstrcpyW( pNewDomain-> m_strActionString, (LPCWSTR)m_strActionString ); pNewDomain-> m_dwActionType = m_dwActionType; pNewDomain-> m_fAllowEtrn = m_fAllowEtrn; // deal with default domain if( m_dwActionType == SMTP_DEFAULT ) { pOldDef = m_pDefaultDomainEntry; pOldDef-> m_dwActionType = pOldDef->m_strActionString[0] ? SMTP_DROP : SMTP_DELIVER; InsertHeadList( &m_list, &pNewDomain->list ); m_pDefaultDomainEntry = pNewDomain; } else { InsertTailList( &m_list, &pNewDomain->list ); } hr = SaveToMetabase(); if( FAILED(hr) ) { RemoveEntryList( &pNewDomain->list ); ErrorTrace ( (LPARAM) this, "Failed to remove domain: %x", hr ); delete pNewDomain; goto Exit; } m_pCurrentDomainEntry = pNewDomain; m_lCount++; Exit: TraceFunctLeave (); return hr; } STDMETHODIMP CSmtpAdminDomain::Remove ( ) { TraceFunctEnter ( "CSmtpAdminDomain::Remove" ); HRESULT hr = NOERROR; // need to call get() first _ASSERT( m_pCurrentDomainEntry ); _ASSERT( !lstrcmpiW( m_strDomainName, m_pCurrentDomainEntry->m_strDomainName ) ); if( !m_pCurrentDomainEntry || lstrcmpiW( m_strDomainName, m_pCurrentDomainEntry->m_strDomainName ) ) { hr = SmtpCreateException (IDS_SMTPEXCEPTION_DIDNT_CALL_GET); goto Exit; } //Can't remove default domain if( m_pCurrentDomainEntry == m_pDefaultDomainEntry ) { hr = SmtpCreateException (IDS_SMTPEXCEPTION_CANT_DEL_DEFAULT_DOMAIN); goto Exit; } RemoveEntryList( &m_pCurrentDomainEntry->list ); hr = SaveToMetabase(); Exit: TraceFunctLeave (); return hr; } STDMETHODIMP CSmtpAdminDomain::Get ( ) { TraceFunctEnter ( "CSmtpAdminDomain::Get" ); HRESULT hr = NOERROR; hr = GetFromMetabase(); if( FAILED(hr) ) { goto Exit; } // given domain name, find the entry m_pCurrentDomainEntry = FindDomainEntry( m_strDomainName ); if( !m_pCurrentDomainEntry ) { hr = SmtpCreateException( IDS_SMTPEXCEPTION_INVALID_ADDRESS ); goto Exit; } LoadDomainProperty( m_pCurrentDomainEntry ); Exit: TraceFunctLeave (); return hr; } STDMETHODIMP CSmtpAdminDomain::Set ( ) { TraceFunctEnter ( "CSmtpAdminDomain::Set" ); HRESULT hr = NOERROR; DomainEntry* pOldDef = NULL; // need to call get() first _ASSERT( m_pCurrentDomainEntry ); if( !m_pCurrentDomainEntry ) { hr = SmtpCreateException (IDS_SMTPEXCEPTION_DIDNT_CALL_GET); goto Exit; } lstrcpyW( m_pCurrentDomainEntry->m_strDomainName, m_strDomainName ); lstrcpyW( m_pCurrentDomainEntry->m_strActionString, m_strActionString ); m_pCurrentDomainEntry-> m_dwActionType = m_dwActionType; m_pCurrentDomainEntry-> m_fAllowEtrn = m_fAllowEtrn; // deal with default domain if( m_dwActionType == SMTP_DEFAULT && m_pDefaultDomainEntry != m_pCurrentDomainEntry ) { pOldDef = m_pDefaultDomainEntry; pOldDef-> m_dwActionType = pOldDef->m_strActionString[0] ? SMTP_DROP : SMTP_DELIVER; m_pDefaultDomainEntry = m_pCurrentDomainEntry; RemoveEntryList( &m_pCurrentDomainEntry->list ); InsertHeadList( &m_list, &m_pCurrentDomainEntry->list ); } hr = SaveToMetabase(); Exit: TraceFunctLeave (); return hr; } STDMETHODIMP CSmtpAdminDomain::Enumerate ( ) { TraceFunctEnter ( "CSmtpAdminDomain::EnumDomains" ); HRESULT hr = NOERROR; hr = GetFromMetabase(); m_fEnumerated = TRUE; TraceFunctLeave (); return hr; } STDMETHODIMP CSmtpAdminDomain::GetNth( long lIndex ) { TraceFunctEnter ( "CSmtpAdminDomain::GetNth" ); HRESULT hr = NOERROR; PLIST_ENTRY pEntry; if( !m_fEnumerated ) { hr = SmtpCreateException( IDS_SMTPEXCEPTION_DIDNT_ENUMERATE ); goto Exit; } if( lIndex < 0 || lIndex >= m_lCount ) { hr = SmtpCreateException( IDS_SMTPEXCEPTION_INVALID_INDEX ); goto Exit; } pEntry = m_list.Flink; while( lIndex -- ) { pEntry = pEntry-> Flink; _ASSERT( pEntry != &m_list ); } m_pCurrentDomainEntry = CONTAINING_RECORD(pEntry, DomainEntry, list); LoadDomainProperty( m_pCurrentDomainEntry ); Exit: TraceFunctLeave (); return hr; } STDMETHODIMP CSmtpAdminDomain::GetDefaultDomain ( ) { TraceFunctEnter ( "CSmtpAdminDomain::GetDefaultDomain" ); HRESULT hr = NOERROR; if( !m_pDefaultDomainEntry ) { hr = GetFromMetabase(); if( FAILED(hr) ) { goto Exit; } } LoadDomainProperty( m_pDefaultDomainEntry ); Exit: TraceFunctLeave (); return hr; } DomainEntry* CSmtpAdminDomain::FindDomainEntry( LPCWSTR lpName ) { TraceFunctEnter ( "CSmtpAdminDomain::FindDomainEntry" ); DomainEntry* pDomainEntry = NULL; PLIST_ENTRY pHead; PLIST_ENTRY pEntry; for( pHead=&m_list, pEntry=pHead->Flink; pEntry!=pHead; pEntry=pEntry->Flink ) { pDomainEntry = CONTAINING_RECORD(pEntry, DomainEntry, list); if( !lstrcmpiW( pDomainEntry->m_strDomainName, lpName ) ) { TraceFunctLeave (); return pDomainEntry; } } TraceFunctLeave (); return NULL; } STDMETHODIMP CSmtpAdminDomain::SetAsDefaultDomain ( ) { TraceFunctEnter ( "CSmtpAdminDomain::SetAsDefaultDomain" ); HRESULT hr = NOERROR; if( !m_pDefaultDomainEntry ) { hr = GetFromMetabase(); if( FAILED(hr) ) { goto Exit; } } // not in the list if( m_dwDomainId == UNASSIGNED_DOMAIN_ID ) { hr = Add(); if( FAILED(hr) ) { goto Exit; } } _ASSERT( m_dwDomainId == m_pCurrentDomainEntry->m_dwDomainId ); m_pDefaultDomainEntry = m_pCurrentDomainEntry; hr = SaveToMetabase(); Exit: TraceFunctLeave (); return hr; } BOOL CSmtpAdminDomain::LoadDomainProperty(DomainEntry* pDomainEntry) { TraceFunctEnter ( "CSmtpAdminDomain::LoadDomainProperty" ); _ASSERT( pDomainEntry ); m_strDomainName = pDomainEntry-> m_strDomainName; m_dwActionType = pDomainEntry-> m_dwActionType; m_strActionString = pDomainEntry-> m_strActionString; m_fAllowEtrn = pDomainEntry-> m_fAllowEtrn; m_dwDomainId = pDomainEntry-> m_dwDomainId; m_pCurrentDomainEntry = pDomainEntry; TraceFunctLeave (); return TRUE; } BOOL CSmtpAdminDomain::ConstructListFromMetabaseValues() { TraceFunctEnter ( "CSmtpAdminDomain::ConstructListFromMetabaseValues" ); DomainEntry* pDomainEntry; TCHAR* pCh; TCHAR* wszCurrent; DWORD i; DWORD cCount = m_mszDomainRouting.Count( ); EmptyList(); m_lCount = 0; pCh = (TCHAR*)(LPCWSTR)m_mszDomainRouting; for( wszCurrent = pCh, i = 0; i < cCount; i++, wszCurrent += lstrlen (wszCurrent) + 1 ) { pDomainEntry = new DomainEntry; if( NULL == pDomainEntry ) { goto Exit; } pDomainEntry-> FromString( wszCurrent ); InsertHeadList( &m_list, &pDomainEntry->list ); } m_lCount += cCount; if( !m_strDefaultDomain.m_str || !m_strDefaultDomain.m_str[0] ) { _ASSERT( FALSE ); goto Exit; } m_pDefaultDomainEntry = new DomainEntry; if( NULL == m_pDefaultDomainEntry ) { goto Exit; } lstrcpy( m_pDefaultDomainEntry-> m_strDomainName, m_strDefaultDomain.m_str ); if( !m_strDropDir ) { m_pDefaultDomainEntry-> m_strActionString[0] = _T('\0'); } else { lstrcpy( m_pDefaultDomainEntry-> m_strActionString, m_strDropDir.m_str ); } m_pDefaultDomainEntry-> m_dwActionType = SMTP_DEFAULT; InsertHeadList( &m_list, &m_pDefaultDomainEntry->list ); m_lCount ++; Exit: TraceFunctLeave (); return TRUE; } BOOL CSmtpAdminDomain::ParseListToMetabaseValues() // called by SaveData() { TraceFunctEnter ( "CSmtpAdminDomain::ParseListToMetabaseValues" ); BOOL fRet = TRUE; // change string list to multisz DomainEntry* pDomainEntry = NULL; PLIST_ENTRY pHead; PLIST_ENTRY pEntry; DWORD cb = 0; WCHAR* pBuf; WCHAR* p; // the first one is default domain _ASSERT( CONTAINING_RECORD( m_list.Flink, DomainEntry, list ) == m_pDefaultDomainEntry ); for( pHead=&m_list, pEntry=pHead->Flink->Flink; pEntry!=pHead; pEntry=pEntry->Flink ) { pDomainEntry = CONTAINING_RECORD(pEntry, DomainEntry, list); cb += lstrlenW( pDomainEntry-> m_strDomainName ); cb += lstrlenW( pDomainEntry-> m_strActionString ); cb += sizeof(DWORD)*2; cb += 10; // 4 commas and NULL } // two more NULL's cb += 4; pBuf = new WCHAR[cb]; if( !pBuf ) { ErrorTrace ( (LPARAM) this, "Out of memory" ); fRet = FALSE; goto Exit; } p = pBuf; // Note: the first entry is the default domain for( pHead=&m_list, pEntry=pHead->Flink->Flink; pEntry!=pHead; pEntry=pEntry->Flink ) { pDomainEntry = CONTAINING_RECORD(pEntry, DomainEntry, list); pDomainEntry->ToString( p ); p += lstrlenW(p); p ++; } // add two more NULL *p = L'\0'; *(p+1) = L'\0'; m_mszDomainRouting.Empty(); m_mszDomainRouting.Attach( pBuf ); Exit: TraceFunctLeave (); return fRet; } HRESULT CSmtpAdminDomain::GetFromMetabase() { TraceFunctEnter ( "CSmtpAdminDomain::GetFromMetabase" ); HRESULT hr = NOERROR; BOOL fRet = TRUE; CComPtr pmetabase; TCHAR szPath[METADATA_MAX_NAME_LEN+2] = {0}; TCHAR szDropDir[256] = {0}; TCHAR szBuf[256] = {0}; hr = m_mbFactory.GetMetabaseObject ( m_iadsImpl.QueryComputer(), &pmetabase ); if ( FAILED(hr) ) { return hr; } CMetabaseKey hMB( pmetabase ); GetMDInstancePath( szPath, m_iadsImpl.QueryInstance() ); hr = hMB.Open( szPath, METADATA_PERMISSION_READ ); if( FAILED(hr) ) { hr = SmtpCreateExceptionFromWin32Error( GetLastError() ); goto Exit; } m_strDefaultDomain.Empty(); m_strDropDir.Empty(); m_mszDomainRouting.Empty(); fRet = StdGetMetabaseProp ( &hMB, MD_DOMAIN_ROUTING, DEFAULT_DOMAIN_ROUTING, &m_mszDomainRouting); fRet = StdGetMetabaseProp ( &hMB, MD_DEFAULT_DOMAIN_VALUE, DEFAULT_DEFAULT_DOMAIN, &m_strDefaultDomain ) && fRet; fRet = StdGetMetabaseProp ( &hMB, MD_MAIL_DROP_DIR, DEFAULT_DROP_DIR, &m_strDropDir ) && fRet; if( !fRet ) { hr = SmtpCreateExceptionFromWin32Error( GetLastError() ); goto Exit; } ConstructListFromMetabaseValues(); Exit: TraceFunctLeave (); return hr; } HRESULT CSmtpAdminDomain::SaveToMetabase() { TraceFunctEnter ( "CSmtpAdminDomain::SaveToMetabase" ); ParseListToMetabaseValues(); // these two are for default domain, // default domain needs special care, // by default, it's computed by smtpsvc from TCP/IP configuration, // don't set this key if not changed BOOL fDefChanged = FALSE; BOOL fDropChanged = FALSE; _ASSERT( m_pDefaultDomainEntry && m_pDefaultDomainEntry-> m_dwActionType == SMTP_DEFAULT ); if( m_pDefaultDomainEntry ) { fDefChanged = lstrcmpiW( m_strDefaultDomain, m_pDefaultDomainEntry-> m_strDomainName ); fDropChanged = lstrcmpiW( m_strActionString, m_pDefaultDomainEntry-> m_strActionString ); if( fDefChanged ) { m_strDefaultDomain.Empty(); m_strDefaultDomain = m_pDefaultDomainEntry-> m_strDomainName; } if( fDropChanged ) { m_strDropDir.Empty(); m_strDropDir = m_pDefaultDomainEntry-> m_strActionString; } } HRESULT hr = NOERROR; BOOL fRet = TRUE; CComPtr pmetabase; TCHAR szPath[METADATA_MAX_NAME_LEN+2] = {0}; TCHAR szDropDir[256] = {0}; TCHAR szBuf[256] = {0}; hr = m_mbFactory.GetMetabaseObject ( m_iadsImpl.QueryComputer(), &pmetabase ); if ( FAILED(hr) ) { return hr; } CMetabaseKey hMB( pmetabase ); GetMDInstancePath( szPath, m_iadsImpl.QueryInstance() ); hr = hMB.Open( szPath, METADATA_PERMISSION_WRITE ); if( FAILED(hr) ) { hr = SmtpCreateExceptionFromWin32Error( GetLastError() ); goto Exit; } if( fDefChanged ) { fRet = StdPutMetabaseProp ( &hMB, MD_DEFAULT_DOMAIN_VALUE, m_pDefaultDomainEntry-> m_strDomainName ) && fRet; } if( fDropChanged ) { fRet = StdPutMetabaseProp ( &hMB, MD_MAIL_DROP_DIR, m_pDefaultDomainEntry-> m_strActionString ) && fRet; } fRet = StdPutMetabaseProp ( &hMB, MD_DOMAIN_ROUTING, &m_mszDomainRouting) && fRet; if( !fRet ) { hr = SmtpCreateExceptionFromWin32Error( GetLastError() ); goto Exit; } // hr = hMB.Close(); // BAIL_ON_FAILURE(hr); hMB.Close(); hr = pmetabase-> SaveData(); BAIL_ON_FAILURE(hr); Exit: TraceFunctLeave (); return hr; } BOOL DomainEntry::FromString( LPCTSTR lpDomainString ) { TraceFunctEnter ( "DomainEntry::FromString" ); TCHAR szT[256] = {0}; WCHAR* pCh = (WCHAR*)lpDomainString; WCHAR* pT; m_dwDomainId = UNASSIGNED_DOMAIN_ID; m_fAllowEtrn = FALSE; ZeroMemory( szT, sizeof(szT) ); pT = szT; while( *pCh ) // { if( iswdigit( *pCh ) ) { *pT++ = *pCh; pCh ++; continue; } if( *pCh == ',' ) { pCh ++; break; } return FALSE; } if( !*pCh ) return FALSE; m_dwActionType = (DWORD) _wtoi( szT ); /* if( m_dwActionType >= LAST_SMTP_ACTION ) { _ASSERT( FALSE ); m_dwActionType = SMTP_DROP; // assume local drop domain } */ ZeroMemory( m_strDomainName, sizeof(m_strDomainName) ); pT = m_strDomainName; while( *pCh ) { if( *pCh == ',' ) { pCh ++; break; } *pT++ = *pCh++; } if( !*pCh ) return FALSE; ZeroMemory( m_strActionString, sizeof(m_strActionString) ); pT = m_strActionString; while( *pCh ) { if( *pCh == ',' ) { pCh ++; break; } *pT++ = *pCh++; } if( !*pCh ) return FALSE; ZeroMemory( szT, sizeof(szT) ); pT = szT; while( *pCh ) // { if( iswdigit( *pCh ) ) { *pT++ = *pCh; pCh ++; continue; } if( *pCh == ',' ) { pCh ++; break; } return FALSE; } m_fAllowEtrn = !! ((DWORD) _wtoi( szT )); if( !*pCh ) { return FALSE; } ZeroMemory( szT, sizeof(szT) ); pT = szT; while( *pCh ) // { if( iswdigit( *pCh ) ) { *pT++ = *pCh; pCh ++; continue; } if( *pCh == ',' ) { pCh ++; break; } return FALSE; } m_dwDomainId = (DWORD) _wtoi( szT ); // ignore any other chars TraceFunctLeave (); return TRUE; } BOOL DomainEntry::ToString( LPTSTR lpDomainString ) { TraceFunctEnter ( "DomainEntry::FromString" ); wsprintfW( lpDomainString, L"%d,%s,%s,%d",m_dwActionType, m_strDomainName, m_strActionString, m_fAllowEtrn); TraceFunctLeave (); return TRUE; }