1163 lines
28 KiB
C++
1163 lines
28 KiB
C++
// 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;
|
|
|
|
hr = StdPropertyHandoffIDispatch (
|
|
CLSID_CNntpVirtualServer,
|
|
IID_INntpVirtualServer,
|
|
&pINntpVirtualServer,
|
|
ppIDispatch
|
|
);
|
|
if ( FAILED(hr) ) {
|
|
goto Error;
|
|
}
|
|
|
|
// Set default properties:
|
|
hr = pINntpVirtualServer->put_Server ( m_strServer ? m_strServer : _T("") );
|
|
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 ];
|
|
|
|
// wsprintf ( wszFullPath, "%s\\%s\\%s", szNntpFileDirectory, szSubkey, szFilename );
|
|
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:
|
|
//
|
|
|
|
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;
|
|
}
|
|
|