// VirtualRoot.cpp : Implementation of CNntpVirtualRoot & CNntpVirtualRoots. #include "stdafx.h" #include "nntpcmn.h" #include "cmultisz.h" #include "vroots.h" #include "oleutil.h" #include "metautil.h" #include "metakey.h" #define THIS_FILE_HELP_CONTEXT 0 #define THIS_FILE_PROG_ID _T("Nntpadm.VirtualServer.1") #define THIS_FILE_IID IID_INntpVirtualServer #define DEFAULT_ACCESS_PERM ( 0 ) CVRoot::CVRoot () : m_dwWin32Error ( 0 ), m_bvAccess ( 0 ), m_bvSslAccess ( 0 ), m_fLogAccess ( TRUE ), m_fIndexContent ( TRUE ), m_dwUseAccount ( 0 ), m_fDoExpire ( FALSE ), m_fOwnModerator ( FALSE ) { } HRESULT CVRoot::SetProperties ( BSTR strNewsgroupSubtree, BSTR strDirectory, DWORD dwWin32Error, DWORD bvAccess, DWORD bvSslAccess, BOOL fLogAccess, BOOL fIndexContent, BSTR strUNCUsername, BSTR strUNCPassword, BSTR strDriverProgId, BSTR strGroupPropFile, DWORD dwUseAccount, BOOL fDoExpire, BOOL fOwnModerator, BSTR strMdbGuid ) { _ASSERT ( IS_VALID_STRING ( strNewsgroupSubtree ) ); _ASSERT ( IS_VALID_STRING ( strDirectory ) ); _ASSERT ( IS_VALID_STRING ( strUNCUsername ) ); _ASSERT ( IS_VALID_STRING ( strUNCPassword ) ); _ASSERT ( IS_VALID_STRING ( strDriverProgId ) ); _ASSERT ( IS_VALID_STRING ( strGroupPropFile ) ); _ASSERT ( IS_VALID_STRING ( strMdbGuid ) ); m_strNewsgroupSubtree = strNewsgroupSubtree; m_strDirectory = strDirectory; m_dwWin32Error = dwWin32Error; m_bvAccess = bvAccess; m_bvSslAccess = bvSslAccess; m_fLogAccess = fLogAccess; m_fIndexContent = fIndexContent; m_strUNCUsername = strUNCUsername; m_strUNCPassword = strUNCPassword; m_strDriverProgId = strDriverProgId; m_strGroupPropFile = strGroupPropFile; m_dwUseAccount = dwUseAccount; m_fDoExpire = fDoExpire; m_fOwnModerator = fOwnModerator, m_strMdbGuid = strMdbGuid; if ( !m_strNewsgroupSubtree || !m_strDirectory || !m_strUNCUsername || !m_strUNCPassword ) { return E_OUTOFMEMORY; } return NOERROR; } HRESULT CVRoot::SetProperties ( INntpVirtualRoot * pVirtualRoot ) { HRESULT hr; BOOL fAllowPosting; BOOL fRestrictVisibility; BOOL fRequireSsl; BOOL fRequire128BitSsl; m_strDirectory.Empty (); m_strUNCUsername.Empty (); m_strUNCPassword.Empty (); m_strDriverProgId.Empty(); m_strGroupPropFile.Empty(); m_strMdbGuid.Empty(); hr = pVirtualRoot->get_NewsgroupSubtree ( &m_strNewsgroupSubtree ); BAIL_ON_FAILURE(hr); hr = pVirtualRoot->get_Directory ( &m_strDirectory ); BAIL_ON_FAILURE(hr); hr = pVirtualRoot->get_Win32Error ( (long *) &m_dwWin32Error ); BAIL_ON_FAILURE(hr); hr = pVirtualRoot->get_UNCUsername ( &m_strUNCUsername ); BAIL_ON_FAILURE(hr); hr = pVirtualRoot->get_UNCPassword ( &m_strUNCPassword ); BAIL_ON_FAILURE(hr); hr = pVirtualRoot->get_DriverProgId ( &m_strDriverProgId ); BAIL_ON_FAILURE( hr ); hr = pVirtualRoot->get_GroupPropFile ( &m_strGroupPropFile ); BAIL_ON_FAILURE( hr ); hr = pVirtualRoot->get_MdbGuid ( &m_strMdbGuid ); BAIL_ON_FAILURE( hr ); hr = pVirtualRoot->get_UseAccount( &m_dwUseAccount ); BAIL_ON_FAILURE( hr ); hr = pVirtualRoot->get_OwnExpire( &m_fDoExpire ); BAIL_ON_FAILURE( hr ); hr = pVirtualRoot->get_OwnModerator( &m_fOwnModerator ); BAIL_ON_FAILURE( hr ); hr = pVirtualRoot->get_LogAccess ( &m_fLogAccess ); _ASSERT ( SUCCEEDED(hr) ); hr = pVirtualRoot->get_IndexContent ( &m_fIndexContent ); _ASSERT ( SUCCEEDED(hr) ); hr = pVirtualRoot->get_AllowPosting ( &fAllowPosting ); _ASSERT ( SUCCEEDED(hr) ); hr = pVirtualRoot->get_RestrictGroupVisibility ( &fRestrictVisibility ); _ASSERT ( SUCCEEDED(hr) ); hr = pVirtualRoot->get_RequireSsl ( &fRequireSsl ); _ASSERT ( SUCCEEDED(hr) ); hr = pVirtualRoot->get_Require128BitSsl ( &fRequire128BitSsl ); _ASSERT ( SUCCEEDED(hr) ); SetBitFlag ( &m_bvAccess, MD_ACCESS_ALLOW_POSTING, fAllowPosting ); SetBitFlag ( &m_bvAccess, MD_ACCESS_RESTRICT_VISIBILITY, fRestrictVisibility ); SetBitFlag ( &m_bvSslAccess, MD_ACCESS_SSL, fRequireSsl ); SetBitFlag ( &m_bvSslAccess, MD_ACCESS_SSL128, fRequire128BitSsl ); Exit: return hr; } HRESULT CVRoot::GetFromMetabase ( CMetabaseKey * pMB, LPCWSTR wszName, DWORD dwInstanceId, LPWSTR wszServerName ) { HRESULT hr = NOERROR; DWORD dwDontLog = TRUE; m_strDirectory.Empty(); m_strUNCUsername.Empty(); m_strUNCPassword.Empty(); StdGetMetabaseProp ( pMB, MD_ACCESS_PERM, 0, &m_bvAccess, wszName ); StdGetMetabaseProp ( pMB, MD_SSL_ACCESS_PERM, 0, &m_bvSslAccess, wszName ); StdGetMetabaseProp ( pMB, MD_DONT_LOG, FALSE, &dwDontLog, wszName ); StdGetMetabaseProp ( pMB, MD_IS_CONTENT_INDEXED, FALSE, &m_fIndexContent, wszName, IIS_MD_UT_FILE); StdGetMetabaseProp ( pMB, MD_VR_PATH, _T(""), &m_strDirectory, wszName ); //StdGetMetabaseProp ( pMB, MD_WIN32_ERROR, 0, &m_dwWin32Error, wszName, IIS_MD_UT_FILE, METADATA_NO_ATTRIBUTES ); StdGetMetabaseProp ( pMB, MD_VR_USERNAME, _T(""), &m_strUNCUsername, wszName ); StdGetMetabaseProp ( pMB, MD_VR_PASSWORD, _T(""), &m_strUNCPassword, wszName, IIS_MD_UT_SERVER, METADATA_SECURE ); StdGetMetabaseProp ( pMB, MD_VR_USE_ACCOUNT, 0, &m_dwUseAccount, wszName ); StdGetMetabaseProp ( pMB, MD_VR_DO_EXPIRE, FALSE, &m_fDoExpire, wszName ); StdGetMetabaseProp ( pMB, MD_VR_OWN_MODERATOR, FALSE, &m_fOwnModerator, wszName ); StdGetMetabaseProp ( pMB, MD_VR_DRIVER_PROGID, _T("NNTP.FSPrepare"), &m_strDriverProgId, wszName ); StdGetMetabaseProp ( pMB, MD_FS_PROPERTY_PATH, m_strDirectory, &m_strGroupPropFile, wszName ); StdGetMetabaseProp ( pMB, MD_EX_MDB_GUID, _T(""), &m_strMdbGuid, wszName ); // // Get the win32 error code from RPC // DWORD dw = NntpGetVRootWin32Error( (LPWSTR)wszServerName, dwInstanceId, (LPWSTR)wszName, (LPDWORD)&m_dwWin32Error ); switch (dw) { case ERROR_SERVICE_NOT_ACTIVE: m_dwWin32Error = dw; break; case NOERROR: break; default: hr = HRESULT_FROM_WIN32( dw ); goto Exit; } m_strNewsgroupSubtree = wszName; m_fLogAccess = !dwDontLog; if ( !m_strNewsgroupSubtree || !m_strDirectory || !m_strUNCUsername || !m_strUNCPassword ) { hr = E_OUTOFMEMORY; goto Exit; } Exit: return hr; } HRESULT CVRoot::SendToMetabase ( CMetabaseKey * pMB, LPCWSTR wszName ) { HRESULT hr = NOERROR; hr = pMB->SetString ( wszName, MD_KEY_TYPE, _T("IIsNntpVirtualDir"), METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER ); BAIL_ON_FAILURE(hr); hr = pMB->SetString ( wszName, MD_VR_PATH, m_strDirectory, METADATA_INHERIT, IIS_MD_UT_FILE ); BAIL_ON_FAILURE(hr); StdPutMetabaseProp ( pMB, MD_ACCESS_PERM, m_bvAccess, wszName, IIS_MD_UT_FILE ); StdPutMetabaseProp ( pMB, MD_SSL_ACCESS_PERM, m_bvSslAccess, wszName, IIS_MD_UT_FILE ); StdPutMetabaseProp ( pMB, MD_DONT_LOG, !m_fLogAccess, wszName, IIS_MD_UT_FILE ); StdPutMetabaseProp ( pMB, MD_IS_CONTENT_INDEXED, m_fIndexContent, wszName, IIS_MD_UT_FILE ); StdPutMetabaseProp ( pMB, MD_WIN32_ERROR, m_dwWin32Error, wszName, IIS_MD_UT_SERVER, METADATA_VOLATILE ); StdPutMetabaseProp ( pMB, MD_VR_USERNAME, m_strUNCUsername, wszName, IIS_MD_UT_FILE ); StdPutMetabaseProp ( pMB, MD_VR_PASSWORD, m_strUNCPassword, wszName, IIS_MD_UT_FILE, METADATA_SECURE | METADATA_INHERIT ); StdPutMetabaseProp ( pMB, MD_VR_USE_ACCOUNT, m_dwUseAccount, wszName, IIS_MD_UT_SERVER ); StdPutMetabaseProp ( pMB, MD_VR_DO_EXPIRE, m_fDoExpire, wszName, IIS_MD_UT_SERVER ); StdPutMetabaseProp ( pMB, MD_VR_OWN_MODERATOR, m_fOwnModerator, wszName, IIS_MD_UT_SERVER ); StdPutMetabaseProp ( pMB, MD_VR_DRIVER_PROGID, m_strDriverProgId, wszName, IIS_MD_UT_SERVER ); StdPutMetabaseProp ( pMB, MD_FS_PROPERTY_PATH, m_strGroupPropFile, wszName, IIS_MD_UT_SERVER ); StdPutMetabaseProp ( pMB, MD_EX_MDB_GUID, m_strMdbGuid, wszName, IIS_MD_UT_SERVER ); Exit: return hr; } ///////////////////////////////////////////////////////////////////////////// // STDMETHODIMP CNntpVirtualRoot::InterfaceSupportsErrorInfo(REFIID riid) { static const IID* arr[] = { &IID_INntpVirtualRoot, }; for (int i=0;i METADATA_MAX_NAME_LEN - 20 ) return CO_E_PATHTOOLONG; return StdPropertyPut ( &m_vroot.m_strNewsgroupSubtree, strNewsgroupSubtree ); } STDMETHODIMP CNntpVirtualRoot::get_Directory ( BSTR * pstrDirectory ) { return StdPropertyGet ( m_vroot.m_strDirectory, pstrDirectory ); } STDMETHODIMP CNntpVirtualRoot::put_Directory ( BSTR strDirectory ) { return StdPropertyPut ( &m_vroot.m_strDirectory, strDirectory ); } STDMETHODIMP CNntpVirtualRoot::get_Win32Error ( long * plWin32Error ) { return StdPropertyGet ( m_vroot.m_dwWin32Error, plWin32Error ); } STDMETHODIMP CNntpVirtualRoot::get_LogAccess ( BOOL * pfLogAccess ) { return StdPropertyGet ( m_vroot.m_fLogAccess, pfLogAccess ); } STDMETHODIMP CNntpVirtualRoot::put_LogAccess ( BOOL fLogAccess ) { return StdPropertyPut ( &m_vroot.m_fLogAccess, fLogAccess ); } STDMETHODIMP CNntpVirtualRoot::get_IndexContent ( BOOL * pfIndexContent ) { return StdPropertyGet ( m_vroot.m_fIndexContent, pfIndexContent ); } STDMETHODIMP CNntpVirtualRoot::put_IndexContent ( BOOL fIndexContent ) { return StdPropertyPut ( &m_vroot.m_fIndexContent, fIndexContent ); } STDMETHODIMP CNntpVirtualRoot::get_AllowPosting ( BOOL * pfAllowPosting ) { return StdPropertyGetBit ( m_vroot.m_bvAccess, MD_ACCESS_ALLOW_POSTING, pfAllowPosting ); } STDMETHODIMP CNntpVirtualRoot::put_AllowPosting ( BOOL fAllowPosting ) { return StdPropertyPutBit ( &m_vroot.m_bvAccess, MD_ACCESS_ALLOW_POSTING, fAllowPosting ); } STDMETHODIMP CNntpVirtualRoot::get_RestrictGroupVisibility ( BOOL * pfRestrictGroupVisibility ) { return StdPropertyGetBit ( m_vroot.m_bvAccess, MD_ACCESS_RESTRICT_VISIBILITY, pfRestrictGroupVisibility ); } STDMETHODIMP CNntpVirtualRoot::put_RestrictGroupVisibility ( BOOL fRestrictGroupVisibility ) { return StdPropertyPutBit ( &m_vroot.m_bvAccess, MD_ACCESS_RESTRICT_VISIBILITY, fRestrictGroupVisibility ); } STDMETHODIMP SSLNegotiateCert ( BOOL * pfSSLNegotiateCert ); STDMETHODIMP SSLNegotiateCert ( BOOL fSSLNegotiateCert ); STDMETHODIMP SSLRequireCert ( BOOL * pfSSLRequireCert ); STDMETHODIMP SSLRequireCert ( BOOL fSSLRequireCert ); STDMETHODIMP SSLMapCert ( BOOL * pfSSLMapCert ); STDMETHODIMP SSLMapCert ( BOOL fSSLMapCert ); STDMETHODIMP CNntpVirtualRoot::get_RequireSsl ( BOOL * pfRequireSsl ) { return StdPropertyGetBit ( m_vroot.m_bvSslAccess, MD_ACCESS_SSL, pfRequireSsl ); } STDMETHODIMP CNntpVirtualRoot::put_RequireSsl ( BOOL fRequireSsl ) { return StdPropertyPutBit ( &m_vroot.m_bvSslAccess, MD_ACCESS_SSL, fRequireSsl ); } STDMETHODIMP CNntpVirtualRoot::get_Require128BitSsl ( BOOL * pfRequire128BitSsl ) { return StdPropertyGetBit ( m_vroot.m_bvSslAccess, MD_ACCESS_SSL128, pfRequire128BitSsl ); } STDMETHODIMP CNntpVirtualRoot::put_Require128BitSsl ( BOOL fRequire128BitSsl ) { return StdPropertyPutBit ( &m_vroot.m_bvSslAccess, MD_ACCESS_SSL128, fRequire128BitSsl ); } STDMETHODIMP CNntpVirtualRoot::get_UNCUsername ( BSTR * pstrUNCUsername ) { return StdPropertyGet ( m_vroot.m_strUNCUsername, pstrUNCUsername ); } STDMETHODIMP CNntpVirtualRoot::put_UNCUsername ( BSTR strUNCUsername ) { return StdPropertyPut ( &m_vroot.m_strUNCUsername, strUNCUsername ); } STDMETHODIMP CNntpVirtualRoot::get_UNCPassword ( BSTR * pstrUNCPassword ) { return StdPropertyGet ( m_vroot.m_strUNCPassword, pstrUNCPassword ); } STDMETHODIMP CNntpVirtualRoot::put_UNCPassword ( BSTR strUNCPassword ) { return StdPropertyPut ( &m_vroot.m_strUNCPassword, strUNCPassword ); } STDMETHODIMP CNntpVirtualRoot::get_DriverProgId( BSTR *pstrDriverProgId ) { return StdPropertyGet( m_vroot.m_strDriverProgId, pstrDriverProgId ); } STDMETHODIMP CNntpVirtualRoot::put_DriverProgId( BSTR strDriverProgId ) { return StdPropertyPut( &m_vroot.m_strDriverProgId, strDriverProgId ); } STDMETHODIMP CNntpVirtualRoot::get_GroupPropFile( BSTR *pstrGroupPropFile ) { return StdPropertyGet( m_vroot.m_strGroupPropFile, pstrGroupPropFile ); } STDMETHODIMP CNntpVirtualRoot::put_GroupPropFile( BSTR strGroupPropFile ) { return StdPropertyPut( &m_vroot.m_strGroupPropFile, strGroupPropFile ); } STDMETHODIMP CNntpVirtualRoot::get_MdbGuid( BSTR *pstrMdbGuid ) { return StdPropertyGet( m_vroot.m_strMdbGuid, pstrMdbGuid ); } STDMETHODIMP CNntpVirtualRoot::put_MdbGuid( BSTR strMdbGuid ) { return StdPropertyPut( &m_vroot.m_strMdbGuid, strMdbGuid ); } STDMETHODIMP CNntpVirtualRoot::get_UseAccount( DWORD *pdwUseAccount ) { return StdPropertyGet( m_vroot.m_dwUseAccount, pdwUseAccount ); } STDMETHODIMP CNntpVirtualRoot::put_UseAccount( DWORD dwUseAccount ) { return StdPropertyPut( &m_vroot.m_dwUseAccount, dwUseAccount ); } STDMETHODIMP CNntpVirtualRoot::get_OwnExpire( BOOL *pfOwnExpire ) { return StdPropertyGet( m_vroot.m_fDoExpire, pfOwnExpire ); } STDMETHODIMP CNntpVirtualRoot::put_OwnExpire( BOOL fOwnExpire ) { return StdPropertyPut( &m_vroot.m_fDoExpire, fOwnExpire ); } STDMETHODIMP CNntpVirtualRoot::get_OwnModerator( BOOL *pfOwnModerator ) { return StdPropertyGet( m_vroot.m_fOwnModerator, pfOwnModerator ); } STDMETHODIMP CNntpVirtualRoot::put_OwnModerator( BOOL fOwnModerator ) { return StdPropertyPut( &m_vroot.m_fOwnModerator, fOwnModerator ); } ///////////////////////////////////////////////////////////////////////////// // STDMETHODIMP CNntpVirtualRoots::InterfaceSupportsErrorInfo(REFIID riid) { static const IID* arr[] = { &IID_INntpVirtualRoots, }; for (int i=0;i pMetabase; // Clear the old enumeration: delete [] m_rgVRoots; m_rgVRoots = NULL; m_dwCount = 0; hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase ); if ( FAILED(hr) ) { goto Exit; } hr = GetVRootsFromMetabase ( pMetabase ); if ( FAILED(hr) ) { goto Exit; } Exit: TRACE_HRESULT(hr); TraceFunctLeave (); return hr; } STDMETHODIMP CNntpVirtualRoots::Item ( long index, INntpVirtualRoot ** ppVirtualRoot ) { TraceFunctEnter ( "CNntpVirtualRoots::Item" ); _ASSERT ( IS_VALID_OUT_PARAM ( ppVirtualRoot ) ); *ppVirtualRoot = NULL; HRESULT hr = NOERROR; CComObject * pVirtualRoot = NULL; if ( index < 0 || index >= m_dwCount ) { hr = NntpCreateException ( IDS_NNTPEXCEPTION_INVALID_INDEX ); goto Exit; } hr = CComObject::CreateInstance ( &pVirtualRoot ); if ( FAILED(hr) ) { goto Exit; } _ASSERT ( pVirtualRoot ); hr = pVirtualRoot->SetProperties ( m_rgVRoots[index] ); if ( FAILED(hr) ) { goto Exit; } hr = pVirtualRoot->QueryInterface ( IID_INntpVirtualRoot, (void **) ppVirtualRoot ); _ASSERT ( SUCCEEDED(hr) ); Exit: if ( FAILED(hr) ) { delete pVirtualRoot; } TRACE_HRESULT(hr); TraceFunctLeave (); return hr; } STDMETHODIMP CNntpVirtualRoots::Add ( INntpVirtualRoot * pVirtualRoot ) { TraceFunctEnter ( "CNntpVirtualRoots::Add" ); _ASSERT ( IS_VALID_IN_PARAM ( pVirtualRoot ) ); HRESULT hr = NOERROR; CVRoot * rgNewVirtualRoots = NULL; long i; CComPtr pMetabase; CVRoot newVroot; WCHAR wszName [ 2*METADATA_MAX_NAME_LEN ]; WCHAR wszVRootPath [ 2*METADATA_MAX_NAME_LEN ]; // Validate the new Virtual Root: hr = newVroot.SetProperties ( pVirtualRoot ); if ( FAILED(hr) ) { return hr; } if ( !newVroot.m_strNewsgroupSubtree || !newVroot.m_strNewsgroupSubtree[0] ) { return RETURNCODETOHRESULT ( ERROR_INVALID_PARAMETER ); } // Add the new virtual root to the metabase: GetVRootName ( newVroot.m_strNewsgroupSubtree, wszName ); // // The sub tree itself should not exceed length METADATA_MAX_NAME_LEN // _ASSERT( wcslen( wszName ) <= METADATA_MAX_NAME_LEN ); if ( wcslen( wszName ) > METADATA_MAX_NAME_LEN ) { return CO_E_PATHTOOLONG; } hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase ); if ( FAILED(hr) ) { return hr; } CMetabaseKey mb ( pMetabase ); GetMDVRootPath ( wszVRootPath ); // // I trust wszVRootPath, it's shorter than METADATA_MAX_NAME_LEN // // // Test to see if this item exists already: // WCHAR wszTempPath [ 2 * METADATA_MAX_NAME_LEN + 1]; wsprintf ( wszTempPath, _T("%s%s"), wszVRootPath, wszName ); if ( wcslen( wszTempPath ) > METADATA_MAX_NAME_LEN ) { // // I can't handle it either // return CO_E_PATHTOOLONG; } hr = mb.Open ( wszTempPath ); if ( SUCCEEDED(hr) ) { DWORD cbVrootDir; if ( SUCCEEDED ( mb.GetDataSize ( _T(""), MD_VR_PATH, STRING_METADATA, &cbVrootDir, METADATA_NO_ATTRIBUTES ) ) ) { mb.Close(); hr = NntpCreateException ( IDS_NNTPEXCEPTION_VROOT_ALREADY_EXISTS ); goto Exit; } } hr = mb.Open ( wszVRootPath, METADATA_PERMISSION_WRITE ); BAIL_ON_FAILURE(hr); /* hr = mb.CreateChild ( wszName ); BAIL_ON_FAILURE(hr); */ hr = newVroot.SendToMetabase ( &mb, wszName ); BAIL_ON_FAILURE(hr); hr = mb.Save (); BAIL_ON_FAILURE(hr); // Allocate the new VirtualRoot array: rgNewVirtualRoots = new CVRoot [ m_dwCount + 1 ]; if ( !rgNewVirtualRoots ) { hr = E_OUTOFMEMORY; goto Exit; } // Copy the old VirtualRoots to the new array: for ( i = 0; i < m_dwCount; i++ ) { hr = rgNewVirtualRoots[i].SetProperties ( m_rgVRoots[i] ); if ( FAILED (hr) ) { goto Exit; } } // Add the new VirtualRoot to the end of the array: hr = rgNewVirtualRoots[m_dwCount].SetProperties ( pVirtualRoot ); if ( FAILED(hr) ) { goto Exit; } _ASSERT ( SUCCEEDED(hr) ); delete [] m_rgVRoots; m_rgVRoots = rgNewVirtualRoots; m_dwCount++; Exit: TraceFunctLeave (); return hr; } STDMETHODIMP CNntpVirtualRoots::Set ( long index, INntpVirtualRoot * pVirtualRoot ) { TraceFunctEnter ( "CNntpVirtualRoots::ChangeVirtualRoot" ); HRESULT hr = NOERROR; CComBSTR strNewsgroupSubtree; CComBSTR strDirectory; CVRoot temp; CComPtr pMetabase; WCHAR wszVRootPath [ METADATA_MAX_NAME_LEN ]; WCHAR wszName [ METADATA_MAX_NAME_LEN ]; // Send the new virtual root to the metabase: hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase ); if ( FAILED(hr) ) { return hr; } CMetabaseKey mb ( pMetabase ); if ( index < 0 || index >= m_dwCount ) { hr = NntpCreateException ( IDS_NNTPEXCEPTION_INVALID_INDEX ); goto Exit; } hr = temp.SetProperties ( pVirtualRoot ); if ( FAILED(hr) ) { goto Exit; } GetMDVRootPath ( wszVRootPath ); hr = mb.Open ( wszVRootPath, METADATA_PERMISSION_WRITE ); BAIL_ON_FAILURE(hr); GetVRootName ( temp.m_strNewsgroupSubtree, wszName ); hr = temp.SendToMetabase ( &mb, wszName ); BAIL_ON_FAILURE(hr); hr = m_rgVRoots[index].SetProperties ( pVirtualRoot ); BAIL_ON_FAILURE(hr); Exit: TraceFunctLeave (); return hr; } STDMETHODIMP CNntpVirtualRoots::Remove ( long index ) { TraceFunctEnter ( "CNntpVirtualRoots::Remove" ); HRESULT hr = NOERROR; CVRoot temp; long cPositionsToSlide; CComPtr pMetabase; WCHAR wszName [ METADATA_MAX_NAME_LEN ]; WCHAR wszVRootPath [ METADATA_MAX_NAME_LEN ]; if ( index < 0 || index >= m_dwCount ) { return NntpCreateException ( IDS_NNTPEXCEPTION_INVALID_INDEX ); } // Delete the virtual root from the metabase: hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase ); if ( FAILED(hr) ) { return hr; } CMetabaseKey mb ( pMetabase ); GetMDVRootPath ( wszVRootPath ); hr = mb.Open ( wszVRootPath, METADATA_PERMISSION_WRITE ); BAIL_ON_FAILURE(hr); GetVRootName ( m_rgVRoots[index].m_strNewsgroupSubtree, wszName ); hr = mb.DeleteAllData ( wszName ); BAIL_ON_FAILURE(hr); /* hr = mb.DestroyChild ( wszName ); BAIL_ON_FAILURE(hr); */ hr = mb.Save (); BAIL_ON_FAILURE(hr); mb.Close (); // Slide the array down by one position: _ASSERT ( m_rgVRoots ); cPositionsToSlide = (m_dwCount - 1) - index; _ASSERT ( cPositionsToSlide < m_dwCount ); if ( cPositionsToSlide > 0 ) { // Save the deleted VirtualRoot in temp: CopyMemory ( &temp, &m_rgVRoots[index], sizeof ( CVRoot ) ); // Move the array down one: MoveMemory ( &m_rgVRoots[index], &m_rgVRoots[index + 1], sizeof ( CVRoot ) * cPositionsToSlide ); // Put the deleted VirtualRoot on the end (so it gets destructed): CopyMemory ( &m_rgVRoots[m_dwCount - 1], &temp, sizeof ( CVRoot ) ); // Zero out the temp VirtualRoot: ZeroMemory ( &temp, sizeof ( CVRoot ) ); } m_dwCount--; Exit: TraceFunctLeave (); return hr; } STDMETHODIMP CNntpVirtualRoots::Find ( BSTR strNewsgroupSubtree, long * pIndex ) { HRESULT hr = NOERROR; long i; _ASSERT ( pIndex ); *pIndex = -1; for ( i = 0; i < m_dwCount; i++ ) { if ( lstrcmp ( m_rgVRoots[i].m_strNewsgroupSubtree, strNewsgroupSubtree ) == 0 ) { *pIndex = i; } } return NOERROR; } static HRESULT CountVrootsIterator ( CMetabaseKey * pMB, LPCWSTR wszVrootPath, LPARAM lParam ) { DWORD * pcVroots = (DWORD *) lParam; (*pcVroots)++; return NOERROR; } typedef struct tagAddVrootsParms { DWORD cCount; CVRoot * rgVroots; DWORD dwCurrentIndex; LPWSTR wszServerName; DWORD dwInstanceId; } ADD_VROOTS_PARMS; static HRESULT AddVrootsIterator ( CMetabaseKey * pMB, LPCWSTR wszVrootPath, LPARAM lParam ) { _ASSERT ( pMB ); _ASSERT ( wszVrootPath ); _ASSERT ( lParam ); HRESULT hr; ADD_VROOTS_PARMS * pParms = (ADD_VROOTS_PARMS *) lParam; LPWSTR wszServerName = pParms->wszServerName; DWORD dwInstanceId = pParms->dwInstanceId; _ASSERT ( pParms->dwCurrentIndex < pParms->cCount ); hr = pParms->rgVroots[pParms->dwCurrentIndex].GetFromMetabase ( pMB, wszVrootPath, dwInstanceId, wszServerName ); BAIL_ON_FAILURE(hr); pParms->dwCurrentIndex++; Exit: return hr; } HRESULT CNntpVirtualRoots::GetVRootsFromMetabase ( IMSAdminBase * pMetabase ) { HRESULT hr = NOERROR; CMetabaseKey mb ( pMetabase ); WCHAR wszVRootPath [ METADATA_MAX_NAME_LEN ]; DWORD cCount = 0; CVRoot * rgVroots = NULL; ADD_VROOTS_PARMS parms; // // Initialize the metabase: // GetMDVRootPath ( wszVRootPath ); hr = mb.Open ( wszVRootPath ); BAIL_ON_FAILURE(hr); // // Count the virtual roots: // hr = IterateOverVroots ( &mb, CountVrootsIterator, (LPARAM) &cCount ); BAIL_ON_FAILURE(hr); // // Create the virtual roots array: // rgVroots = new CVRoot [ cCount ]; if ( !rgVroots ) { hr = E_OUTOFMEMORY; goto Exit; } // // Add the virtual roots to the array: // parms.cCount = cCount; parms.rgVroots = rgVroots; parms.dwCurrentIndex = 0; parms.wszServerName = m_strServer; parms.dwInstanceId = m_dwServiceInstance; hr = IterateOverVroots ( &mb, AddVrootsIterator, (LPARAM) &parms ); BAIL_ON_FAILURE(hr); _ASSERT ( SUCCEEDED(hr) ); _ASSERT ( m_rgVRoots == NULL ); m_rgVRoots = rgVroots; m_dwCount = cCount; Exit: if ( FAILED(hr) ) { delete [] rgVroots; } return hr; } HRESULT CNntpVirtualRoots::IterateOverVroots ( CMetabaseKey * pMB, VROOT_ITERATOR fpIterator, LPARAM lParam, LPCWSTR wszPath // = _T("") ) { HRESULT hr; WCHAR wszSubKey[ METADATA_MAX_NAME_LEN ]; WCHAR wszSubPath[ METADATA_MAX_NAME_LEN ]; BOOL fRealVroot; DWORD cbVrootDir; DWORD i; // // Is this a real vroot? // fRealVroot = !*wszPath || // Always count the home directory SUCCEEDED ( pMB->GetDataSize ( wszPath, MD_VR_PATH, STRING_METADATA, &cbVrootDir, METADATA_NO_ATTRIBUTES ) ); if ( fRealVroot ) { // Call the iterator on this key: hr = (*fpIterator) ( pMB, wszPath, lParam ); BAIL_ON_FAILURE(hr); } // // Recurse down the tree: // for ( i = 0; ; ) { hr = pMB->EnumObjects ( wszPath, wszSubKey, i ); if ( HRESULTTOWIN32(hr) == ERROR_NO_MORE_ITEMS ) { // This is expected, end the loop: if ( !fRealVroot && i == 0 ) { // // This key isn't a vroot and has no children, so delete it. // hr = pMB->ChangePermissions ( METADATA_PERMISSION_WRITE ); if ( SUCCEEDED(hr) ) { hr = pMB->DeleteKey ( wszPath ); } pMB->ChangePermissions ( METADATA_PERMISSION_READ ); if ( SUCCEEDED(hr) ) { hr = pMB->Save (); } if ( SUCCEEDED(hr) ) { // // Tell our parent that this key was deleted. // hr = S_FALSE; } else { // // Ignore any deleting problems: // hr = NOERROR; } } else { hr = NOERROR; } break; } BAIL_ON_FAILURE(hr); if ( *wszPath ) { if ( _snwprintf ( wszSubPath, sizeof(wszSubKey)/sizeof(wszSubKey[0]) - 1, _T("%s/%s"), wszPath, wszSubKey ) < 0 ) { // Theoretically impossible because of the name length restriction of metabase // If it really happens, skip the recursive call and go on to the next one hr = NOERROR; i++; continue; } else { wszSubPath[sizeof(wszSubKey)/sizeof(wszSubKey[0]) - 1] = L'\0'; } } else { wcscpy ( wszSubPath, wszSubKey ); } hr = IterateOverVroots ( pMB, fpIterator, lParam, wszSubPath ); BAIL_ON_FAILURE(hr); if ( hr != S_FALSE ) { // // This means the child key still exists, so increment // the counter and go on to the next one. // i++; } // // Else the return code is S_FALSE, which means the current key // has been deleted, shifting all indicies down by one. Therefore, // there is no need to increment i. // } Exit: return hr; } void CNntpVirtualRoots::GetVRootName ( LPWSTR wszDisplayName, LPWSTR wszPathName ) { wcscpy ( wszPathName, wszDisplayName ); } void CNntpVirtualRoots::GetMDVRootPath ( LPWSTR wszPath ) { GetMDInstancePath ( wszPath, m_dwServiceInstance ); wcscat ( wszPath, _T("Root/") ); } STDMETHODIMP CNntpVirtualRoots::ItemDispatch ( long index, IDispatch ** ppDispatch ) { HRESULT hr; CComPtr pVirtualRoot; hr = Item ( index, &pVirtualRoot ); BAIL_ON_FAILURE ( hr ); hr = pVirtualRoot->QueryInterface ( IID_IDispatch, (void **) ppDispatch ); BAIL_ON_FAILURE ( hr ); Exit: return hr; } STDMETHODIMP CNntpVirtualRoots::AddDispatch ( IDispatch * pVirtualRoot ) { HRESULT hr; CComPtr pINntpVirtualRoot; hr = pVirtualRoot->QueryInterface ( IID_INntpVirtualRoot, (void **) &pINntpVirtualRoot ); BAIL_ON_FAILURE(hr); hr = Add ( pINntpVirtualRoot ); BAIL_ON_FAILURE(hr); Exit: return hr; } STDMETHODIMP CNntpVirtualRoots::SetDispatch ( long lIndex, IDispatch * pVirtualRoot ) { HRESULT hr; CComPtr pINntpVirtualRoot; hr = pVirtualRoot->QueryInterface ( IID_INntpVirtualRoot, (void **) &pINntpVirtualRoot ); BAIL_ON_FAILURE(hr); hr = Set ( lIndex, pINntpVirtualRoot ); BAIL_ON_FAILURE(hr); Exit: return hr; }