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.
 
 
 
 
 
 

1174 lines
30 KiB

// admin.cpp : Implementation of CnntpadmApp and DLL registration.
#include "stdafx.h"
#include "nntpcmn.h"
#include "oleutil.h"
#include "cmultisz.h"
#include "metautil.h"
#include "metakey.h"
#include "admin.h"
#include "version.h"
#define NNTP_DEF_SERVICE_VERSION ( 0 )
#define DEFAULT_SERVER_BINDINGS _T(":119:\0")
#define DEFAULT_SECURE_BINDINGS _T(":563:\0")
// Must define THIS_FILE_* macros to use NntpCreateException()
#define THIS_FILE_HELP_CONTEXT 0
#define THIS_FILE_PROG_ID _T("Nntpadm.Admin.1")
#define THIS_FILE_IID IID_INntpAdmin
//
// Metabase key strings used by CreateNewInstance:
//
const WCHAR * g_cszFeeds = _T("Feeds");
const WCHAR * g_cszExpires = _T("Expires");
const WCHAR * g_cszRoot = _T("Root");
const WCHAR * g_cszBindingPoints = _T("BindingPoints");
const WCHAR * g_cszDDropCLSID = _T("{8b4316f4-af73-11d0-b0ba-00aa00c148be}");
const WCHAR * g_cszBindings = _T("Bindings");
const WCHAR * g_cszDDrop = _T("ddrop");
const WCHAR * g_cszDescription = _T("Description");
const WCHAR * g_cszPriority = _T("Priority");
const WCHAR * g_cszProgID = _T("ProgID");
const WCHAR * g_cszDDropDescription = _T("NNTP Directory Drop");
const WCHAR * g_cszDDropPriority = _T("4");
const WCHAR * g_cszDDropProgID = _T("DDropNNTP.Filter");
/////////////////////////////////////////////////////////////////////////////
//
CNntpAdmin::CNntpAdmin () :
m_dwServiceVersion ( 0 ),
m_dwServiceInstance ( 0 )
// CComBSTR's are initialized to NULL by default.
{
InitAsyncTrace ( );
}
CNntpAdmin::~CNntpAdmin ()
{
// All CComBSTR's are freed automatically.
TermAsyncTrace ( );
}
STDMETHODIMP CNntpAdmin::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_INntpAdmin,
};
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
/*
STDMETHODIMP CNntpAdmin::get_ServiceAdmin ( IDispatch ** ppIDispatch )
{
HRESULT hr = NOERROR;
CComPtr<INntpService> pINntpService;
hr = StdPropertyHandoffIDispatch (
CLSID_CNntpService,
IID_INntpService,
&pINntpService,
ppIDispatch
);
if ( FAILED(hr) ) {
goto Error;
}
// Set default properties:
hr = pINntpService->put_Server ( m_strServer ? m_strServer : _T("") );
if ( FAILED (hr) ) {
goto Error;
}
return hr;
Error:
SAFE_RELEASE ( *ppIDispatch );
*ppIDispatch = NULL;
return hr;
// Destructor releases pINntpAdminExpiration
}
*/
STDMETHODIMP CNntpAdmin::get_ServerAdmin ( IDispatch ** ppIDispatch )
{
HRESULT hr = NOERROR;
CComPtr<INntpVirtualServer> pINntpVirtualServer;
CComBSTR strTemp = _T("");
if (!strTemp)
{
hr = E_OUTOFMEMORY;
goto Error;
}
hr = StdPropertyHandoffIDispatch (
CLSID_CNntpVirtualServer,
IID_INntpVirtualServer,
&pINntpVirtualServer,
ppIDispatch
);
if ( FAILED(hr) ) {
goto Error;
}
// Set default properties:
hr = pINntpVirtualServer->put_Server ( m_strServer ? m_strServer : strTemp );
if ( FAILED (hr) ) {
goto Error;
}
hr = pINntpVirtualServer->put_ServiceInstance ( m_dwServiceInstance );
if ( FAILED (hr) ) {
goto Error;
}
return hr;
Error:
SAFE_RELEASE ( *ppIDispatch );
*ppIDispatch = NULL;
return hr;
// Destructor releases pINntpVirtualServer
}
// Which service to configure:
STDMETHODIMP CNntpAdmin::get_Server ( BSTR * pstrServer )
{
return StdPropertyGet ( m_strServer, pstrServer );
}
STDMETHODIMP CNntpAdmin::put_Server ( BSTR strServer )
{
return StdPropertyPutServerName ( &m_strServer, strServer );
}
STDMETHODIMP CNntpAdmin::get_ServiceInstance ( long * plServiceInstance )
{
return StdPropertyGet ( m_dwServiceInstance, plServiceInstance );
}
STDMETHODIMP CNntpAdmin::put_ServiceInstance ( long lServiceInstance )
{
return StdPropertyPut ( &m_dwServiceInstance, lServiceInstance );
}
// Versioning:
STDMETHODIMP CNntpAdmin::get_HighVersion ( long * plHighVersion )
{
*plHighVersion = HIGH_VERSION;
return NOERROR;
}
STDMETHODIMP CNntpAdmin::get_LowVersion ( long * plLowVersion )
{
*plLowVersion = LOW_VERSION;
return NOERROR;
}
STDMETHODIMP CNntpAdmin::get_BuildNum ( long * plBuildNumber )
{
*plBuildNumber = CURRENT_BUILD_NUMBER;
return NOERROR;
}
STDMETHODIMP CNntpAdmin::get_ServiceVersion ( long * plServiceVersion )
{
*plServiceVersion = m_dwServiceVersion;
return NOERROR;
}
//////////////////////////////////////////////////////////////////////
// Methods:
//////////////////////////////////////////////////////////////////////
//$-------------------------------------------------------------------
//
// CNntpAdmin::EnumerateInstances
//
// Description:
//
// Returns a list of the virtual servers on the given machine.
//
// Parameters:
//
// ppsaInstances - Returned SAFEARRAY of instance IDs.
// Must be freed by caller.
// pErr - Error return code.
//
// Returns:
//
// Error code in *pErr.
//
//--------------------------------------------------------------------
STDMETHODIMP CNntpAdmin::EnumerateInstances ( SAFEARRAY ** ppsaInstances)
{
TraceFunctEnter ( "CNntpAdmin::EnumerateInstances" );
HRESULT hr = NOERROR;
CComPtr<IMSAdminBase> pMetabase;
SAFEARRAY * psaEmpty = NULL;
SAFEARRAYBOUND sabound[1];
// Check parameters:
_ASSERT ( ppsaInstances != NULL );
_ASSERT ( IS_VALID_OUT_PARAM ( ppsaInstances ) );
if ( ppsaInstances == NULL ) {
FatalTrace ( 0, "Bad return pointer" );
hr = E_POINTER;
goto Exit;
}
// Zero the out parameters:
*ppsaInstances = NULL;
// Set the return array to an empty array:
sabound[0].lLbound = 0;
sabound[0].cElements = 0;
psaEmpty = SafeArrayCreate ( VT_I4, 1, sabound );
if ( psaEmpty == NULL ) {
FatalTrace ( (LPARAM) this, "Out of memory" );
hr = E_OUTOFMEMORY;
goto Exit;
}
*ppsaInstances = psaEmpty;
// Get the metabase pointer:
hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase );
if ( FAILED(hr) ) {
goto Exit;
}
// Enumerate the instances:
hr = QueryMetabaseInstances ( pMetabase, ppsaInstances );
if ( FAILED(hr) ) {
goto Exit;
}
Exit:
if ( FAILED(hr) ) {
_VERIFY ( SUCCEEDED (SafeArrayDestroy ( psaEmpty )) );
if (ppsaInstances)
*ppsaInstances = NULL;
}
TRACE_HRESULT ( hr );
TraceFunctLeave ();
return hr;
}
STDMETHODIMP CNntpAdmin::EnumerateInstancesVariant ( SAFEARRAY ** ppsaInstances)
{
TraceFunctEnter ( "CNntpAdmin::EnumerateInstancesVariant" );
HRESULT hr;
SAFEARRAY * psaInstances = NULL;
hr = EnumerateInstances ( &psaInstances );
BAIL_ON_FAILURE(hr);
hr = LongArrayToVariantArray ( psaInstances, ppsaInstances );
BAIL_ON_FAILURE(hr);
Exit:
TraceFunctLeave ();
return hr;
}
//$-------------------------------------------------------------------
//
// CNntpAdmin::CreateInstance
//
// Description:
//
// Creates a new NNTP virtual server on the given machine.
//
// Parameters:
//
// strNntpFileDirectory - Directory where all the hash files go.
// strHomeDirectory - Path of the home directory vroot.
// plInstanceId - The new virtual server ID.
// pErr - Resulting error code.
//
// Returns:
//
// Error condition in *pErr.
//
//--------------------------------------------------------------------
STDMETHODIMP CNntpAdmin::CreateInstance (
BSTR strNntpFileDirectory,
BSTR strHomeDirectory,
BSTR strProgId,
BSTR strMdbGuid,
long * plInstanceId
)
{
TraceFunctEnter ( "CNntpAdmin::CreateInstance" );
HRESULT hr = NOERROR;
CComPtr<IMSAdminBase> pMetabase;
// Check parameters:
_ASSERT ( IS_VALID_STRING ( strNntpFileDirectory ) );
_ASSERT ( IS_VALID_STRING ( strHomeDirectory ) );
_ASSERT ( IS_VALID_OUT_PARAM ( plInstanceId ) );
if ( !strNntpFileDirectory || !strHomeDirectory ) {
FatalTrace ( 0, "Bad String Pointer" );
hr = E_POINTER;
goto Exit;
}
if ( !plInstanceId ) {
FatalTrace ( 0, "Bad return pointer" );
hr = E_POINTER;
goto Exit;
}
// Zero the out parameter:
*plInstanceId = 0;
// Get the metabase pointer:
hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase );
if ( FAILED(hr) ) {
goto Exit;
}
// Create a new instance:
hr = CreateNewInstance (
pMetabase,
strNntpFileDirectory,
strHomeDirectory,
strProgId,
strMdbGuid,
plInstanceId
);
if ( FAILED(hr) ) {
goto Exit;
}
Exit:
TRACE_HRESULT(hr);
TraceFunctLeave ();
return hr;
}
//$-------------------------------------------------------------------
//
// CNntpAdmin::DestroyInstance
//
// Description:
//
// Removes the given virtual server.
//
// Parameters:
//
// lInstanceId - The ID of the virtual server to delete.
// pErr - Resulting error code.
//
// Returns:
//
// Error code in *pErr.
//
//--------------------------------------------------------------------
STDMETHODIMP CNntpAdmin::DestroyInstance ( long lInstanceId )
{
TraceFunctEnter ( "CNntpAdmin::DestroyInstance" );
HRESULT hr = NOERROR;
CComPtr<IMSAdminBase> pMetabase;
if ( lInstanceId == 0 ) {
hr = NntpCreateException ( IDS_NNTPEXCEPTION_SERVICE_INSTANCE_CANT_BE_ZERO );
goto Exit;
}
if ( lInstanceId == 1 ) {
hr = NntpCreateException ( IDS_NNTPEXCEPTION_CANT_DELETE_DEFAULT_INSTANCE );
goto Exit;
}
// Get the metabase pointer:
hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase );
if ( FAILED(hr) ) {
goto Exit;
}
// Delete the instance:
hr = DeleteInstance ( pMetabase, lInstanceId );
if ( FAILED(hr) ) {
goto Exit;
}
Exit:
TRACE_HRESULT(hr);
TraceFunctLeave ();
return hr;
}
//$-------------------------------------------------------------------
//
// CNntpAdmin::ErrorToString
//
// Description:
//
// Translates an NNTP_ERROR_CODE to a readable string.
//
// Parameters:
//
// lErrorCode - Win32 error code.
// pstrError - the readable error string.
//
// Returns:
//
// The error string in *pstrError.
//
//--------------------------------------------------------------------
STDMETHODIMP CNntpAdmin::ErrorToString ( long lErrorCode, BSTR * pstrError )
{
TraceFunctEnter ( "CNntpAdmin::ErrorToString" );
_ASSERT ( IS_VALID_OUT_PARAM ( pstrError ) );
HRESULT hr = NOERROR;
WCHAR wszError [ 1024 ];
if ( pstrError == NULL ) {
FatalTrace ( (LPARAM) this, "Bad return pointer" );
hr = E_POINTER;
goto Exit;
}
Win32ErrorToString ( lErrorCode, wszError, 1024 );
*pstrError = ::SysAllocString( wszError );
if ( *pstrError == NULL ) {
hr = E_OUTOFMEMORY;
goto Exit;
}
Exit:
TRACE_HRESULT(hr);
TraceFunctLeave ();
return hr;
}
//$-------------------------------------------------------------------
//
// CNntpAdmin::Tokenize
//
// Description:
//
// Makes the given string safe for HTML & Javascript
//
// Parameters:
//
// strIn - the input string
// strOut - the resulting string with appropriate escape sequences.
//
//--------------------------------------------------------------------
STDMETHODIMP CNntpAdmin::Tokenize ( BSTR strIn, BSTR * pstrOut )
{
TraceFunctEnter ( "CNntpAdmin::Tokenize" );
_ASSERT ( IS_VALID_STRING ( strIn ) );
_ASSERT ( IS_VALID_OUT_PARAM ( pstrOut ) );
HRESULT hr = NOERROR;
PWCHAR pSrc = strIn;
PWCHAR pSrcCur = NULL;
PWCHAR pDstCur = NULL;
PWCHAR pDst = NULL;
*pstrOut = NULL;
pDst = new WCHAR [ 3 * lstrlen ( strIn ) + 1 ];
if ( pDst == NULL ) {
FatalTrace ( (LPARAM) this, "Out of memory" );
hr = E_OUTOFMEMORY;
goto Exit;
}
for ( pSrcCur = pSrc, pDstCur = pDst; *pSrcCur; pSrcCur++ ) {
switch ( *pSrcCur ) {
case L'\\':
*(pDstCur++) = L'%';
*(pDstCur++) = L'5';
*(pDstCur++) = L'c';
break;
case L' ':
*(pDstCur++) = L'+';
break;
case L':':
*(pDstCur++) = L'%';
*(pDstCur++) = L'3';
*(pDstCur++) = L'a';
break;
case L'/':
*(pDstCur++) = L'%';
*(pDstCur++) = L'2';
*(pDstCur++) = L'f';
break;
default:
*(pDstCur++) = *pSrcCur;
}
}
*pDstCur = L'\0';
*pstrOut = ::SysAllocString ( pDst );
if ( *pstrOut == NULL ) {
FatalTrace ( (LPARAM) this, "Out of memory" );
hr = E_OUTOFMEMORY;
goto Exit;
}
Exit:
delete pDst;
TRACE_HRESULT(hr);
TraceFunctLeave ();
return hr;
}
//$-------------------------------------------------------------------
//
// CNntpAdmin::Truncate
//
// Description:
//
// Cuts off a string to a certain length using '...'
//
// Parameters:
//
// strIn - The input string.
// cMaxChars - The maximum characters allowed in the resulting string.
// pstrOut - The resulting (possibly truncated) string.
//
// Returns:
//
//
//
//--------------------------------------------------------------------
STDMETHODIMP CNntpAdmin::Truncate ( BSTR strIn, long cMaxChars, BSTR * pstrOut )
{
TraceFunctEnter ( "CNntpAdmin::Truncate" );
PWCHAR pSrc = strIn;
PWCHAR pDst = NULL;
DWORD cDst = cMaxChars;
HRESULT hr = NOERROR;
*pstrOut = NULL;
if ( wcslen( pSrc ) <= cDst ) {
pDst = pSrc;
} else {
pDst = ::SysAllocStringLen( pSrc, cDst + 1 );
if ( !pDst ) {
FatalTrace ( (LPARAM) this, "Out of memory" );
hr = E_OUTOFMEMORY;
goto Exit;
}
wcscpy( pDst + cDst - 3, L"..." );
}
*pstrOut = pDst;
Exit:
TRACE_HRESULT(hr);
TraceFunctLeave ();
return hr;
}
//$-------------------------------------------------------------------
//
// CNntpAdmin::QueryMetabaseInstances
//
// Description:
//
// Retrieves the list of virtual servers from the metabase
//
// Parameters:
//
// pMetabase - the metabase object
// ppsaInstances - resulting array of instance ids.
// pErr - resulting error code.
//
// Returns:
//
// Error code in *pErr. If *pErr = 0 then an array of IDs in ppsaInstances.
//
//--------------------------------------------------------------------
HRESULT CNntpAdmin::QueryMetabaseInstances ( IMSAdminBase * pMetabase, SAFEARRAY ** ppsaInstances )
{
TraceFunctEnter ( "CNntpAdmin::QueryMetabaseInstances" );
_ASSERT ( IS_VALID_IN_PARAM ( pMetabase ) );
_ASSERT ( IS_VALID_OUT_PARAM ( ppsaInstances ) );
HRESULT hr = NOERROR;
CMetabaseKey mkeyNntp ( pMetabase );
SAFEARRAY * psaResult = NULL;
DWORD cValidInstances = 0;
SAFEARRAYBOUND rgsaBound[1];
DWORD i;
WCHAR wszName[ METADATA_MAX_NAME_LEN ];
long index[1];
DWORD dwInstance;
hr = mkeyNntp.Open ( NNTP_MD_ROOT_PATH );
if ( FAILED(hr) ) {
ErrorTraceX ( (LPARAM) this, "Failed to open NntpSvc key, %x", hr );
hr = HRESULT_FROM_WIN32 ( ERROR_SERVICE_DOES_NOT_EXIST );
goto Exit;
}
// pickup the service version number:
hr = mkeyNntp.GetDword ( MD_NNTP_SERVICE_VERSION, &m_dwServiceVersion );
if ( FAILED(hr) ) {
m_dwServiceVersion = NNTP_DEF_SERVICE_VERSION;
}
hr = mkeyNntp.GetIntegerChildCount ( &cValidInstances );
if ( FAILED(hr) ) {
goto Exit;
}
// Allocate the array:
rgsaBound[0].lLbound = 0;
rgsaBound[0].cElements = cValidInstances;
psaResult = SafeArrayCreate ( VT_I4, 1, rgsaBound );
if ( psaResult == NULL ) {
FatalTrace ( 0, "Out of memory" );
hr = E_OUTOFMEMORY;
goto Exit;
}
mkeyNntp.BeginChildEnumeration ();
for ( i = 0; i < cValidInstances; i++ ) {
hr = mkeyNntp.NextIntegerChild ( &dwInstance, wszName );
_ASSERT ( SUCCEEDED(hr) );
index[0] = i;
hr = SafeArrayPutElement ( psaResult, index, &dwInstance );
_ASSERT ( SUCCEEDED(hr) );
}
*ppsaInstances = psaResult;
_ASSERT ( SUCCEEDED(hr) );
Exit:
if ( FAILED (hr) ) {
SafeArrayDestroy ( psaResult );
}
TraceFunctLeave ();
return hr;
}
HRESULT WriteNntpFileLocation (
CMetabaseKey * pmkeyNntp,
LPCWSTR wszSubkey,
LPCWSTR wszNntpFileDirectory,
LPCWSTR wszFilename,
DWORD mdValue
)
{
HRESULT hr;
WCHAR wszFullPath [ MAX_PATH ];
if (wcslen( wszNntpFileDirectory )+1+wcslen( wszFilename )+1 > MAX_PATH )
return HRESULT_FROM_WIN32 ( ERROR_FILENAME_EXCED_RANGE );
wsprintf ( wszFullPath, _T("%s\\%s"), wszNntpFileDirectory, wszFilename );
hr = pmkeyNntp->SetString ( wszSubkey, mdValue, wszFullPath );
return hr;
}
//$-------------------------------------------------------------------
// CNntpAdmin::CreateVRoot
//
// Description:
//
// Create a vroot for the new instance
//
// Parameters:
//
// CMetabaseKey &mkeyNntp - The metabase key object
// BSTR strVPath - The vroot path
// BSTR strProgId - The prog id to identify vroot type
// LPWSTR wszKeyPath - The key path to set values to
//
// Returns:
//
// HRESULT
//
//--------------------------------------------------------------------
HRESULT CNntpAdmin::CreateVRoot(
CMetabaseKey &mkeyNntp,
BSTR strVPath,
BSTR strProgId,
BSTR strMdbGuid,
LPWSTR wszKeyPath
)
{
TraceFunctEnter( "CNntpAdmin::CreateVRoot" );
HRESULT hr = S_OK;
hr = mkeyNntp.SetString ( wszKeyPath, MD_KEY_TYPE, L"IIsNntpVirtualDir", METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER);
BAIL_ON_FAILURE(hr);
hr = mkeyNntp.SetString ( wszKeyPath, MD_VR_PATH, strVPath );
BAIL_ON_FAILURE(hr);
if ( NULL == strProgId || *strProgId == 0 || _wcsicmp( strProgId, L"NNTP.FSPrepare" ) == 0 ) {
//
// File system driver case
//
hr = mkeyNntp.SetString ( wszKeyPath, MD_FS_PROPERTY_PATH, strVPath );
BAIL_ON_FAILURE(hr);
if ( *strVPath == L'\\' && *(strVPath+1) == L'\\' ) { // UNC
hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_USE_ACCOUNT, 1 );
BAIL_ON_FAILURE( hr );
} else { // regular file system
hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_USE_ACCOUNT, 0 );
}
hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_DO_EXPIRE, 0 );
BAIL_ON_FAILURE( hr );
hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_OWN_MODERATOR, 0 );
BAIL_ON_FAILURE( hr );
} else {
//
// Exchange store driver
//
hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_USE_ACCOUNT, 0 );
BAIL_ON_FAILURE( hr );
hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_DO_EXPIRE, 1 );
BAIL_ON_FAILURE( hr );
hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_OWN_MODERATOR, 1 );
BAIL_ON_FAILURE( hr );
hr = mkeyNntp.SetString( wszKeyPath, MD_EX_MDB_GUID, strMdbGuid );
BAIL_ON_FAILURE( hr );
}
if (NULL == strProgId || *strProgId == 0) {
hr = mkeyNntp.SetString ( wszKeyPath, MD_VR_DRIVER_PROGID, L"NNTP.FSPrepare" );
} else {
hr = mkeyNntp.SetString ( wszKeyPath, MD_VR_DRIVER_PROGID, strProgId );
}
BAIL_ON_FAILURE(hr);
hr = mkeyNntp.SetDword ( wszKeyPath, MD_ACCESS_PERM, MD_ACCESS_READ | MD_ACCESS_WRITE );
BAIL_ON_FAILURE(hr);
Exit:
TraceFunctLeave();
return hr;
}
//$-------------------------------------------------------------------
//
// CNntpAdmin::CreateNewInstance
//
// Description:
//
// Creates a new virtual server in the metabase.
//
// Parameters:
//
// pMetabase - The metabase object
// plInstanceId - The new instance ID.
// pErr - The resulting error code
//
// Returns:
//
// Resulting error code in *pErr. If *pErr = 0, then the new
// ID in plInstanceId.
//
//--------------------------------------------------------------------
HRESULT CNntpAdmin::CreateNewInstance (
IMSAdminBase * pMetabase,
BSTR strNntpFileDirectory,
BSTR strHomeDirectory,
BSTR strProgId,
BSTR strMdbGuid,
long * plInstanceId
)
{
TraceFunctEnter ( "CNntpAdmin::CreateNewInstance" );
_ASSERT ( IS_VALID_IN_PARAM ( pMetabase ) );
_ASSERT ( IS_VALID_IN_PARAM ( strNntpFileDirectory ) );
_ASSERT ( IS_VALID_IN_PARAM ( strHomeDirectory ) );
_ASSERT ( IS_VALID_OUT_PARAM ( plInstanceId ) );
HRESULT hr = NOERROR;
CMetabaseKey mkeyNntp ( pMetabase );
DWORD dwInstance;
WCHAR wszInstance [ METADATA_MAX_NAME_LEN ];
WCHAR wszHomeDirKey [ METADATA_MAX_NAME_LEN ];
WCHAR wszSpecialDirKey[ METADATA_MAX_NAME_LEN ];
WCHAR wszSpecialDirectory[ MAX_PATH * 2 ];
WCHAR wszControlDirKey [ METADATA_MAX_NAME_LEN ];
WCHAR wszControlDirectory[ MAX_PATH * 2 ];
WCHAR wszBuf [ METADATA_MAX_NAME_LEN * 2 ];
WCHAR wszFeedTempDir [ MAX_PATH * 2 ];
CMultiSz mszBindings;
DWORD dwLen;
// Zero the out parameter:
*plInstanceId = NULL;
mszBindings = DEFAULT_SERVER_BINDINGS;
//
// Convert strings to ascii:
//
if (lstrlen(strNntpFileDirectory)+1>MAX_PATH)
{
HRESULT_FROM_WIN32 ( ERROR_FILENAME_EXCED_RANGE );
goto Exit;
}
hr = mkeyNntp.Open ( NNTP_MD_ROOT_PATH, METADATA_PERMISSION_WRITE );
if ( FAILED(hr) ) {
ErrorTraceX ( (LPARAM) this, "Failed to open NntpSvc key, %x", hr );
goto Exit;
}
hr = mkeyNntp.CreateIntegerChild ( &dwInstance, wszInstance );
if ( FAILED (hr) ) {
goto Exit;
}
//
// Write out the subkeys of the instance key:
//
wsprintf ( wszBuf, _T("%s/%s"), wszInstance, g_cszFeeds );
hr = mkeyNntp.CreateChild ( wszBuf );
BAIL_ON_FAILURE ( hr );
wsprintf ( wszFeedTempDir, _T("%s\\%s"), strNntpFileDirectory, _T("_temp.files_") );
mkeyNntp.SetString ( wszBuf, MD_FEED_PEER_TEMP_DIRECTORY, wszFeedTempDir );
BAIL_ON_FAILURE ( hr );
wsprintf ( wszBuf, _T("%s/%s"), wszInstance, g_cszExpires );
hr = mkeyNntp.CreateChild ( wszBuf );
BAIL_ON_FAILURE ( hr );
wsprintf ( wszHomeDirKey, _T("%s/%s"), wszInstance, g_cszRoot );
hr = mkeyNntp.CreateChild ( wszHomeDirKey );
BAIL_ON_FAILURE ( hr );
//
// Set MD_KEY_TYPE for each key:
//
hr = mkeyNntp.SetString ( wszInstance, MD_KEY_TYPE, _T("IIsNntpServer"), METADATA_NO_ATTRIBUTES );
BAIL_ON_FAILURE ( hr );
hr = mkeyNntp.SetString ( wszHomeDirKey, MD_KEY_TYPE, _T("IIsNntpVirtualDir"), METADATA_NO_ATTRIBUTES );
BAIL_ON_FAILURE(hr);
//
// Write out the file locations:
//
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("descrip.txt"), MD_GROUP_HELP_FILE );
BAIL_ON_FAILURE(hr);
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("group.lst"), MD_GROUP_LIST_FILE );
BAIL_ON_FAILURE(hr);
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("groupvar.lst"), MD_GROUPVAR_LIST_FILE );
BAIL_ON_FAILURE(hr);
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("article.hsh"), MD_ARTICLE_TABLE_FILE );
BAIL_ON_FAILURE(hr);
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("history.hsh"), MD_HISTORY_TABLE_FILE );
BAIL_ON_FAILURE(hr);
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("moderatr.txt"), MD_MODERATOR_FILE );
BAIL_ON_FAILURE(hr);
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("xover.hsh"), MD_XOVER_TABLE_FILE );
BAIL_ON_FAILURE(hr);
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("pickup"), MD_PICKUP_DIRECTORY );
BAIL_ON_FAILURE(hr);
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("failedpickup"), MD_FAILED_PICKUP_DIRECTORY );
BAIL_ON_FAILURE(hr);
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("drop"), MD_DROP_DIRECTORY );
BAIL_ON_FAILURE(hr);
hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("prettynm.txt"), MD_PRETTYNAMES_FILE);
BAIL_ON_FAILURE(hr);
//
// Set the default vroot:
//
dwLen = wcslen( wszHomeDirKey );
_ASSERT( dwLen > 0 );
if ( dwLen == 0 ) hr = E_INVALIDARG;
BAIL_ON_FAILURE(hr);
hr = CreateVRoot( mkeyNntp,
strHomeDirectory,
strProgId,
strMdbGuid,
wszHomeDirKey );
BAIL_ON_FAILURE(hr);
//
// Set the special vroots
//
if ( dwLen + wcslen(L"_slavegroup") >= METADATA_MAX_NAME_LEN - 2 )
hr = HRESULT_FROM_WIN32( RPC_S_STRING_TOO_LONG );
BAIL_ON_FAILURE(hr);
if ( *(wszHomeDirKey + dwLen - 1 ) == L'/' ) *(wszHomeDirKey + dwLen - 1 ) = 0;
wcscpy(wszControlDirKey, wszHomeDirKey);
wcscat(wszControlDirKey, L"/control");
wcscat( wszHomeDirKey, L"/_slavegroup" );
//
// For the special _slavegroup vroot, we need to see if strProgId is "NNTP.ExDriverPrepare"
// If so, we need to re-calculate re-calculate wszSpecialDirectory as follow
//
if (_wcsicmp(L"NNTP.ExDriverPrepare", strProgId) == 0)
{
// the default Vroot with the new instance is Exchange Vroot
// re-calculate wszSpecialDirectory
wcscpy( wszSpecialDirectory, strNntpFileDirectory );
dwLen = wcslen( wszSpecialDirectory );
if ( dwLen > 0 && *(wszSpecialDirectory + dwLen - 1 ) == L'/' )
*(wszSpecialDirectory + dwLen - 1 ) = 0;
wcscpy(wszControlDirectory, wszSpecialDirectory);
wcscat( wszControlDirectory, L"\\root\\control" );
wcscat( wszSpecialDirectory, L"\\root\\_slavegroup" );
}
else
{
wcscpy( wszSpecialDirectory, strHomeDirectory );
dwLen = wcslen( wszSpecialDirectory );
if ( dwLen > 0 && *(wszSpecialDirectory + dwLen - 1 ) == L'/' )
*(wszSpecialDirectory + dwLen - 1 ) = 0;
wcscpy(wszControlDirectory, wszSpecialDirectory);
wcscat( wszControlDirectory, L"\\control" );
wcscat( wszSpecialDirectory, L"\\_slavegroup" );
}
hr = CreateVRoot( mkeyNntp,
wszSpecialDirectory,
L"NNTP.FSPrepare",
NULL,
wszHomeDirKey );
BAIL_ON_FAILURE(hr);
//
// Create the control groups on the file system
//
hr = CreateVRoot( mkeyNntp,
wszControlDirectory,
L"NNTP.FSPrepare",
NULL,
wszControlDirKey );
BAIL_ON_FAILURE(hr);
//
// Write out the default bindings:
//
StdPutMetabaseProp ( &mkeyNntp, MD_SERVER_BINDINGS, &mszBindings, wszInstance );
//
// Initialize the server state:
//
mkeyNntp.SetDword ( wszInstance, MD_SERVER_COMMAND, MD_SERVER_COMMAND_STOP );
mkeyNntp.SetDword ( wszInstance, MD_SERVER_STATE, MD_SERVER_STATE_STOPPED );
mkeyNntp.SetDword ( wszInstance, MD_SERVER_AUTOSTART, FALSE );
mkeyNntp.SetDword ( wszInstance, MD_WIN32_ERROR, ERROR_SERVICE_REQUEST_TIMEOUT, METADATA_VOLATILE );
//
// Save all the changes:
//
hr = mkeyNntp.Save ( );
BAIL_ON_FAILURE(hr)
mkeyNntp.Close ();
//
// Now see if the service picked things up successfully:
//
DWORD dwSleepTotal;
DWORD dwWin32Error;
WCHAR wszNewInstanceKey [ METADATA_MAX_NAME_LEN * 2 ];
GetMDInstancePath ( wszNewInstanceKey, dwInstance );
for ( dwWin32Error = ERROR_SERVICE_REQUEST_TIMEOUT, dwSleepTotal = 0;
dwWin32Error == ERROR_SERVICE_REQUEST_TIMEOUT && dwSleepTotal < MAX_SLEEP_INST;
dwSleepTotal += SLEEP_INTERVAL
) {
HRESULT hr2;
Sleep ( SLEEP_INTERVAL );
hr2 = mkeyNntp.Open ( wszNewInstanceKey );
_ASSERT ( SUCCEEDED(hr2) );
hr2 = mkeyNntp.GetDword ( MD_WIN32_ERROR, &dwWin32Error );
_ASSERT ( SUCCEEDED(hr2) );
}
if ( dwWin32Error != NOERROR ) {
HRESULT hr2;
//
// The service reported an error.
// Delete the new instance key
//
hr2 = mkeyNntp.Open ( NNTP_MD_ROOT_PATH, METADATA_PERMISSION_WRITE );
_ASSERT ( SUCCEEDED(hr2) );
hr2 = mkeyNntp.DestroyChild ( wszInstance );
_ASSERT ( SUCCEEDED(hr2) );
hr2 = mkeyNntp.Save ();
_ASSERT ( SUCCEEDED(hr2) );
hr = HRESULT_FROM_WIN32 ( dwWin32Error );
goto Exit;
}
*plInstanceId = dwInstance;
Exit:
TraceFunctLeave ();
return hr;
}
//$-------------------------------------------------------------------
//
// CNntpAdmin::DeleteInstance
//
// Description:
//
// Removes a virtual server from the metabase
//
// Parameters:
//
// pMetabase - The metabase object
// lInstanceId - The ID of the virtual server to delete.
// pErr - The resulting error code.
//
// Returns:
//
// Resulting error code in *pErr.
//
//--------------------------------------------------------------------
HRESULT CNntpAdmin::DeleteInstance ( IMSAdminBase * pMetabase, long lInstanceId )
{
TraceFunctEnter ( "CNntpAdmin::CreateNewInstance" );
_ASSERT ( IS_VALID_IN_PARAM ( pMetabase ) );
HRESULT hr = NOERROR;
CMetabaseKey mkeyNntp ( pMetabase );
//
// Tell U2 to delete any mappings associated with this virtual server:
//
::DeleteMapping ( m_strServer, (BSTR) MD_SERVICE_NAME, lInstanceId );
//
// Delete the virtual server from the metabase:
//
hr = mkeyNntp.Open ( NNTP_MD_ROOT_PATH );
if ( FAILED(hr) ) {
ErrorTraceX ( (LPARAM) this, "Failed to open NntpSvc key, %x", GetLastError() );
goto Exit;
}
hr = mkeyNntp.DestroyIntegerChild ( (DWORD) lInstanceId );
if ( FAILED (hr) ) {
goto Exit;
}
hr = mkeyNntp.Save ();
BAIL_ON_FAILURE(hr);
Exit:
TraceFunctLeave ();
return hr;
}