windows-nt/Source/XPSP1/NT/inetsrv/iis/ui/admin/fscfg/fscfg.cpp
2020-09-26 16:20:57 +08:00

2634 lines
51 KiB
C++

/*++
Copyright (c) 1994-1998 Microsoft Corporation
Module Name :
fscfg.cpp
Abstract:
FTP Configuration Module
Author:
Ronald Meijer (ronaldm)
Project:
Internet Services Manager
Revision History:
--*/
//
// Include Files
//
#include "stdafx.h"
#include "fscfg.h"
#include "fservic.h"
#include "facc.h"
#include "fmessage.h"
#include "vdir.h"
#include "security.h"
#include "wizard.h"
#include "..\mmc\constr.h"
//
// Standard Configuration Information
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#define SVC_ID INET_FTP_SVC_ID
#define INETSLOC_MASK (INET_FTP_SVCLOC_ID)
//
// Service capabilities flags
//
#define SERVICE_INFO_FLAGS (\
ISMI_UNDERSTANDINSTANCE | \
ISMI_INSTANCES | \
ISMI_CHILDREN | \
ISMI_INETSLOCDISCOVER | \
ISMI_CANCONTROLSERVICE | \
ISMI_CANPAUSESERVICE | \
ISMI_TASKPADS | \
ISMI_SECURITYWIZARD | \
ISMI_HASWEBPROTOCOL | \
ISMI_SUPPORTSMETABASE | \
ISMI_SUPPORTSMASTER | \
ISMI_NORMALTBMAPPING)
//
// Name used for this service by the service controller manager.
//
#define SERVICE_SC_NAME _T("MSFTPSVC")
//
// Short descriptive name of the service. This
// is what will show up as the name of the service
// in the internet manager tool.
//
// Issue: I'm assuming here that this name does NOT
// require localisation.
//
#define SERVICE_SHORT_NAME _T("FTP")
//
// Longer name. This is the text that shows up in
// the tooltips text on the internet manager
// tool. This probably should be localised.
//
#define SERVICE_LONG_NAME _T("FTP Service")
//
// Web browser protocol name. e.g. xxxxx://address
// A blank string if this is not supported.
//
#define SERVICE_PROTOCOL _T("ftp")
//
// Toolbar button background mask. This is
// the colour that gets masked out in
// the bitmap file and replaced with the
// actual button background. This setting
// is automatically assumed to be lt. gray
// if NORMAL_TB_MAPPING (above) is TRUE
//
#define BUTTON_BMP_BACKGROUND RGB(192, 192, 192) // Lt. Gray
//
// Resource ID of the toolbar button bitmap.
//
// The bitmap must be 16x16
//
#define BUTTON_BMP_ID IDB_FTP
//
// Similar to BUTTON_BMP_BACKGROUND, this is the
// background mask for the service ID
//
#define SERVICE_BMP_BACKGROUND RGB(255,0,255) // Purple
//
// Bitmap id which is used in the service view
// of the service manager. This may be the same
// bitmap as BUTTON_BMP_BACKGROUND.
//
// The bitmap must be 16x16.
//
#define SERVICE_BMP_ID IDB_FTPVIEW
//
// /* K2 */
//
// Similar to BUTTON_BMP_BACKGROUND, this is the
// background mask for the child bitmap
//
#define CHILD_BMP_BACKGROUND RGB(255, 0, 255) // Purple
//
// /* K2 */
//
// Bitmap id which is used for the child bitmap
//
// The bitmap must be 16x16.
//
#define CHILD_BMP_ID IDB_FTPDIR
#define CHILD_BMP32_ID IDB_FTPDIR32
//
// /* K2 */
//
// Large bitmap (32x32) id
//
#define SERVICE_BMP32_ID IDB_FTPVIEW32
//
// Service Name
//
const LPCTSTR g_cszSvc = _T("MSFTPSVC");
//
// Help IDs
//
#define HIDD_DIRECTORY_PROPERTIES (0x207DB)
#define HIDD_HOME_DIRECTORY_PROPERTIES (HIDD_DIRECTORY_PROPERTIES + 0x20000)
//
// End Of Standard configuration Information
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CFTPInstanceProps::CFTPInstanceProps(
IN LPCTSTR lpszServerName,
IN DWORD dwInstance OPTIONAL
)
/*++
Routine Description:
Constructor for FTP instance properties
Arguments:
LPCTSTR lpszServerName : Server name
DWORD dwInstance : Instance number (could be MASTER_INSTANCE)
Return Value:
N/A
--*/
: CInstanceProps(lpszServerName, g_cszSvc, dwInstance, 21U),
m_nMaxConnections((LONG)0L),
m_nConnectionTimeOut((LONG)0L),
m_dwLogType(MD_LOG_TYPE_DISABLED),
/**/
m_strUserName(),
m_strPassword(),
m_fAllowAnonymous(FALSE),
m_fOnlyAnonymous(FALSE),
m_fPasswordSync(TRUE),
m_acl(),
/**/
m_strExitMessage(),
m_strMaxConMsg(),
m_strlWelcome(),
/**/
m_fDosDirOutput(TRUE),
/**/
m_dwDownlevelInstance(1)
{
//
// Fetch everything
//
m_dwMDUserType = ALL_METADATA;
m_dwMDDataType = ALL_METADATA;
}
/* virtual */
void
CFTPInstanceProps::ParseFields()
/*++
Routine Description:
Break into fields.
Arguments:
None.
Return Value:
None.
--*/
{
//
// Fetch base properties
//
CInstanceProps::ParseFields();
BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
//
// Service Page
//
HANDLE_META_RECORD(MD_MAX_CONNECTIONS, m_nMaxConnections)
HANDLE_META_RECORD(MD_CONNECTION_TIMEOUT, m_nConnectionTimeOut)
HANDLE_META_RECORD(MD_LOG_TYPE, m_dwLogType)
//
// Accounts Page
//
HANDLE_META_RECORD(MD_ANONYMOUS_USER_NAME, m_strUserName)
HANDLE_META_RECORD(MD_ANONYMOUS_PWD, m_strPassword)
HANDLE_META_RECORD(MD_ANONYMOUS_ONLY, m_fOnlyAnonymous)
HANDLE_META_RECORD(MD_ALLOW_ANONYMOUS, m_fAllowAnonymous)
HANDLE_META_RECORD(MD_ANONYMOUS_USE_SUBAUTH, m_fPasswordSync)
HANDLE_META_RECORD(MD_ADMIN_ACL, m_acl)
//
// Message Page
//
HANDLE_META_RECORD(MD_EXIT_MESSAGE, m_strExitMessage)
HANDLE_META_RECORD(MD_MAX_CLIENTS_MESSAGE, m_strMaxConMsg)
HANDLE_META_RECORD(MD_GREETING_MESSAGE, m_strlWelcome)
//
// Directory Properties Page
//
HANDLE_META_RECORD(MD_MSDOS_DIR_OUTPUT, m_fDosDirOutput);
END_PARSE_META_RECORDS
}
/* virtual */
HRESULT
CFTPInstanceProps::WriteDirtyProps()
/*++
Routine Description:
Write the dirty properties to the metabase
Arguments:
None
Return Value:
HRESULT
--*/
{
CError err(CInstanceProps::WriteDirtyProps());
if (err.Failed())
{
return err;
}
BEGIN_META_WRITE()
//
// Service Page
//
META_WRITE(MD_MAX_CONNECTIONS, m_nMaxConnections)
META_WRITE(MD_CONNECTION_TIMEOUT, m_nConnectionTimeOut)
META_WRITE(MD_LOG_TYPE, m_dwLogType)
//
// Accounts Page
//
META_WRITE(MD_ANONYMOUS_USER_NAME, m_strUserName)
META_WRITE(MD_ANONYMOUS_PWD, m_strPassword)
META_WRITE(MD_ANONYMOUS_ONLY, m_fOnlyAnonymous)
META_WRITE(MD_ALLOW_ANONYMOUS, m_fAllowAnonymous)
META_WRITE(MD_ANONYMOUS_USE_SUBAUTH, m_fPasswordSync)
META_WRITE(MD_ADMIN_ACL, m_acl)
//
// Message Page
//
META_WRITE(MD_EXIT_MESSAGE, m_strExitMessage)
META_WRITE(MD_MAX_CLIENTS_MESSAGE, m_strMaxConMsg)
META_WRITE(MD_GREETING_MESSAGE, m_strlWelcome)
//
// Directory Properties Page
//
META_WRITE(MD_MSDOS_DIR_OUTPUT, m_fDosDirOutput);
END_META_WRITE(err);
return err;
}
CFTPDirProps::CFTPDirProps(
IN LPCTSTR lpszServerName,
IN DWORD dwInstance, OPTIONAL
IN LPCTSTR lpszParent, OPTIONAL
IN LPCTSTR lpszAlias OPTIONAL
)
/*++
Routine Description:
FTP Directory properties object
Arguments:
LPCTSTR lpszServerName : Server name
DWORD dwInstance : Instance number (could be MASTER_INSTANCE)
LPCTSTR lpszParent : Parent path (could be NULL)
LPCTSTR lpszAlias : Alias name (could be NULL)
Return Value:
N/A.
--*/
: CChildNodeProps(
lpszServerName,
g_cszSvc,
dwInstance,
lpszParent,
lpszAlias,
WITH_INHERITANCE,
FALSE // Complete information
),
/**/
m_fDontLog(FALSE),
m_ipl()
{
//
// Fetch everything
//
m_dwMDUserType = ALL_METADATA;
m_dwMDDataType = ALL_METADATA;
}
/* virtual */
void
CFTPDirProps::ParseFields()
/*++
Routine Description:
Break into fields.
Arguments:
None.
Return Value:
None.
--*/
{
//
// Fetch base properties
//
CChildNodeProps::ParseFields();
BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
HANDLE_META_RECORD(MD_VR_USERNAME, m_strUserName)
HANDLE_META_RECORD(MD_VR_PASSWORD, m_strPassword)
HANDLE_META_RECORD(MD_DONT_LOG, m_fDontLog);
HANDLE_META_RECORD(MD_IP_SEC, m_ipl);
END_PARSE_META_RECORDS
}
/* virtual */
HRESULT
CFTPDirProps::WriteDirtyProps()
/*++
Routine Description:
Write the dirty properties to the metabase
Arguments:
None
Return Value:
HRESULT
--*/
{
CError err(CChildNodeProps::WriteDirtyProps());
if (err.Failed())
{
return err;
}
//
// CODEWORK: Consider DDX/DDV like methods which do both
// ParseFields and WriteDirtyProps in a single method. Must
// take care not to write data which should only be read, not
// written
//
BEGIN_META_WRITE()
META_WRITE(MD_VR_USERNAME, m_strUserName)
META_WRITE(MD_VR_PASSWORD, m_strPassword)
META_WRITE(MD_DONT_LOG, m_fDontLog);
META_WRITE(MD_IP_SEC, m_ipl);
END_META_WRITE(err);
return err;
}
CFtpSheet::CFtpSheet(
LPCTSTR pszCaption,
LPCTSTR lpszServer,
DWORD dwInstance,
LPCTSTR lpszParent,
LPCTSTR lpszAlias,
CWnd * pParentWnd,
LPARAM lParam,
LONG_PTR handle,
UINT iSelectPage
)
/*++
Routine Description:
FTP Property sheet constructor
Arguments:
LPCTSTR pszCaption : Sheet caption
LPCTSTR lpszServer : Server name
DWORD dwInstance : Instance number
LPCTSTR lpszParent : Parent path
LPCTSTR lpszAlias : Alias name
CWnd * pParentWnd : Parent window
LPARAM lParam : Parameter for MMC console
LONG_PTR handle : MMC console handle
UINT iSelectPage : Initial page selected or -1
Return Value:
N/A
--*/
: CInetPropertySheet(
pszCaption,
lpszServer,
g_cszSvc,
dwInstance,
lpszParent,
lpszAlias,
pParentWnd,
lParam,
handle,
iSelectPage
),
m_ppropInst(NULL),
m_ppropDir(NULL)
{
}
CFtpSheet::~CFtpSheet()
/*++
Routine Description:
FTP Sheet destructor
Arguments:
N/A
Return Value:
N/A
--*/
{
FreeConfigurationParameters();
//
// Must be deleted by now
//
ASSERT(m_ppropInst == NULL);
ASSERT(m_ppropDir == NULL);
}
void
CFtpSheet::WinHelp(
IN DWORD dwData,
IN UINT nCmd
)
/*++
Routine Description:
FTP Property sheet help handler
Arguments:
DWORD dwData : WinHelp data (dialog ID)
UINT nCmd : WinHelp command
Return Value:
None
Notes:
Replace the dialog ID if this is the directory tab. We have
different help depending on virtual directory, home, file, directory.
--*/
{
ASSERT(m_ppropDir != NULL);
if (::lstrcmpi(m_ppropDir->QueryAlias(), g_cszRoot) == 0
&& dwData == HIDD_DIRECTORY_PROPERTIES)
{
//
// It's a home virtual directory -- change the ID
//
dwData = HIDD_HOME_DIRECTORY_PROPERTIES;
}
CInetPropertySheet::WinHelp(dwData, nCmd);
}
/* virtual */
HRESULT
CFtpSheet::LoadConfigurationParameters()
/*++
Routine Description:
Load configuration parameters information
Arguments:
None
Return Value:
HRESULT
--*/
{
CError err;
if (m_ppropInst == NULL)
{
ASSERT(m_ppropDir == NULL);
m_ppropInst = new CFTPInstanceProps(m_strServer, m_dwInstance);
m_ppropDir = new CFTPDirProps(
m_strServer,
m_dwInstance,
m_strParent,
m_strAlias
);
if (!m_ppropInst || !m_ppropDir)
{
err = ERROR_NOT_ENOUGH_MEMORY;
return err;
}
err = m_ppropInst->LoadData();
if (err.Succeeded())
{
err = m_ppropDir->LoadData();
}
}
return err;
}
/* virtual */
void
CFtpSheet::FreeConfigurationParameters()
/*++
Routine Description:
Clean up configuration data
Arguments:
None
Return Value:
None
--*/
{
//
// Must be deleted by now
//
ASSERT(m_ppropInst != NULL);
ASSERT(m_ppropDir != NULL);
SAFE_DELETE(m_ppropInst);
SAFE_DELETE(m_ppropDir);
}
//
// Message Map
//
BEGIN_MESSAGE_MAP(CFtpSheet, CInetPropertySheet)
//{{AFX_MSG_MAP(CInetPropertySheet)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//
// Global DLL instance
//
HINSTANCE hInstance;
//
// ISM API Functions
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
extern "C" DWORD APIENTRY
ISMQueryServiceInfo(
OUT ISMSERVICEINFO * psi
)
/*++
Routine Description:
Return service-specific information back to the application. This
function is called by the service manager immediately after LoadLibary();
The size element must be set prior to calling this API.
Arguments:
ISMSERVICEINFO * psi : Service information returned.
Return Value:
Error return code
--*/
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ASSERT(psi != NULL);
ASSERT(psi->dwSize == ISMSERVICEINFO_SIZE);
psi->dwSize = ISMSERVICEINFO_SIZE;
psi->dwVersion = ISM_VERSION;
psi->flServiceInfoFlags = SERVICE_INFO_FLAGS;
psi->ullDiscoveryMask = INETSLOC_MASK;
psi->rgbButtonBkMask = BUTTON_BMP_BACKGROUND;
psi->nButtonBitmapID = BUTTON_BMP_ID;
psi->rgbServiceBkMask = SERVICE_BMP_BACKGROUND;
psi->nServiceBitmapID = SERVICE_BMP_ID;
psi->rgbServiceBkMask = SERVICE_BMP_BACKGROUND;
psi->nLargeServiceBitmapID = SERVICE_BMP32_ID;
ASSERT(::lstrlen(SERVICE_LONG_NAME) <= MAX_LNLEN);
ASSERT(::lstrlen(SERVICE_SHORT_NAME) <= MAX_SNLEN);
::lstrcpy(psi->atchShortName, SERVICE_SHORT_NAME);
::lstrcpy(psi->atchLongName, SERVICE_LONG_NAME);
//
// /* K2 */
//
psi->rgbChildBkMask = CHILD_BMP_BACKGROUND;
psi->nChildBitmapID = CHILD_BMP_ID ;
psi->rgbLargeChildBkMask = CHILD_BMP_BACKGROUND;
psi->nLargeChildBitmapID = CHILD_BMP32_ID;
//
// IIS 5
//
ASSERT(::lstrlen(SERVICE_PROTOCOL) <= MAX_SNLEN);
ASSERT(::lstrlen(g_cszSvc) <= MAX_SNLEN);
::lstrcpy(psi->atchProtocol, SERVICE_PROTOCOL);
::lstrcpy(psi->atchMetaBaseName, g_cszSvc);
return ERROR_SUCCESS;
}
DWORD APIENTRY
ISMDiscoverServers(
OUT ISMSERVERINFO * psi,
IN DWORD * pdwBufferSize,
IN int * cServers
)
/*++
Routine Description:
Discover machines running this service. This is only necessary
for services not discovered with inetsloc (which don't give a mask)
Arguments:
ISMSERVERINFO * psi : Server info buffer.
DWORD * pdwBufferSize : Size required/available.
int * cServers : Number of servers in buffer.
Return Value:
Error return code
--*/
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
*cServers = 0;
*pdwBufferSize = 0L;
//
// We're an inetsloc service
//
TRACEEOLID("Warning: service manager called bogus ISMDiscoverServers");
ASSERT(FALSE);
return ERROR_SUCCESS;
}
extern "C" DWORD APIENTRY
ISMQueryServerInfo(
IN LPCTSTR lpszServerName,
OUT ISMSERVERINFO * psi
)
/*++
Routine Description:
Get information about a specific server with regards to this service.
Arguments:
LPCTSTR lpszServerName : Name of server.
ISMSERVERINFO * psi : Server information returned.
Return Value:
Error return code
--*/
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ASSERT(psi != NULL);
ASSERT(psi->dwSize == ISMSERVERINFO_SIZE);
ASSERT(::lstrlen(lpszServerName) <= MAX_SERVERNAME_LEN);
psi->dwSize = ISMSERVERINFO_SIZE;
::lstrcpy(psi->atchServerName, lpszServerName);
//
// Start with NULL comment
//
*psi->atchComment = _T('\0');
//
// First look at the SC
//
CError err(::QueryInetServiceStatus(
psi->atchServerName,
SERVICE_SC_NAME,
&(psi->nState)
));
if (err.Failed())
{
psi->nState = INetServiceUnknown;
return err;
}
//
// Check the metabase to see if the service is installed
//
CMetaKey mk(lpszServerName, METADATA_PERMISSION_READ, g_cszSvc);
err = mk.QueryResult();
if (err.Failed())
{
if (err == REGDB_E_CLASSNOTREG)
{
//
// Ok, the service is there, but the metabase is not.
// This must be the old IIS 1-3 version of this service,
// which doesn't count as having the service installed.
//
return ERROR_SERVICE_DOES_NOT_EXIST;
}
return err;
}
//
// If not exist, return bogus acceptable error
//
return (err.Win32Error() == ERROR_PATH_NOT_FOUND)
? ERROR_SERVICE_DOES_NOT_EXIST
: err.Win32Error();
}
extern "C" DWORD APIENTRY
ISMChangeServiceState(
IN int nNewState,
OUT int * pnCurrentState,
IN DWORD dwInstance,
IN LPCTSTR lpszServers
)
/*++
Routine Description:
Change the service state of the servers (to paused/continue, started,
stopped, etc)
Arguments:
int nNewState : INetService definition.
int * pnCurrentState : Ptr to current state (will be changed
DWORD dwInstance : Instance or 0 for the service itself
LPCTSTR lpszServers : Double NULL terminated list of servers.
Return Value:
Error return code
--*/
{
AFX_MANAGE_STATE(AfxGetStaticModuleState() );
ASSERT(nNewState >= INetServiceStopped
&& nNewState <= INetServicePaused);
if (IS_MASTER_INSTANCE(dwInstance))
{
//
// Service itself is referred to here
//
return ChangeInetServiceState(
lpszServers,
SERVICE_SC_NAME,
nNewState,
pnCurrentState
);
}
//
// Change the state of the instance
//
CInstanceProps inst(lpszServers, g_cszSvc, dwInstance);
inst.LoadData();
CError err(inst.ChangeState(nNewState));
*pnCurrentState = inst.QueryISMState();
return err;
}
extern "C" DWORD APIENTRY
ISMConfigureServers(
IN HWND hWnd,
IN DWORD dwInstance,
IN LPCTSTR lpszServers
)
/*++
Routine Description:
Display configuration property sheet.
Arguments:
HWND hWnd : Main app window handle
DWORD dwInstance : Instance number
LPCTSTR lpszServers : Double NULL terminated list of servers
Return Value:
Error return code
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
DWORD err = ERROR_SUCCESS;
//
// Convert the list of servers to a
// more manageable CStringList.
//
CStringList strlServers;
err = ConvertDoubleNullListToStringList(lpszServers, strlServers);
if (err != ERROR_SUCCESS)
{
TRACEEOLID("Error building server string list");
return err;
}
CString strCaption;
if (strlServers.GetCount() == 1)
{
CString str;
LPCTSTR lpComputer = PURE_COMPUTER_NAME(lpszServers);
if(IS_MASTER_INSTANCE(dwInstance))
{
VERIFY(str.LoadString(IDS_CAPTION_DEFAULT));
strCaption.Format(str, lpComputer);
}
else
{
VERIFY(str.LoadString(IDS_CAPTION));
strCaption.Format(str, dwInstance, lpComputer);
}
}
else // Multiple server caption
{
VERIFY(strCaption.LoadString(IDS_CAPTION_MULTIPLE));
}
ASSERT(strlServers.GetCount() == 1);
//
// Get the server name
//
LPCTSTR lpszServer = strlServers.GetHead();
CFtpSheet * pSheet = NULL;
try
{
pSheet = new CFtpSheet(
strCaption,
lpszServer,
dwInstance,
NULL,
g_cszRoot,
CWnd::FromHandlePermanent(hWnd)
);
pSheet->AddRef();
if (SUCCEEDED(pSheet->QueryInstanceResult()))
{
//
// Add instance pages
//
pSheet->AddPage(new CFtpServicePage(pSheet));
pSheet->AddPage(new CFtpAccountsPage(pSheet));
pSheet->AddPage(new CFtpMessagePage(pSheet));
}
if (SUCCEEDED(pSheet->QueryDirectoryResult()))
{
//
// Add home directory pages for the home directory
//
pSheet->AddPage(new CFtpDirectoryPage(pSheet, TRUE));
pSheet->AddPage(new CFtpSecurityPage(pSheet));
}
}
catch(CMemoryException * e)
{
TRACEEOLID("Aborting because of exception");
err = ERROR_NOT_ENOUGH_MEMORY;
e->Delete();
}
if (err == ERROR_SUCCESS)
{
ASSERT(pSheet != NULL);
pSheet->DoModal();
pSheet->Release();
}
//
// Sheet and pages clean themselves up
//
return err;
}
//
// K2 Functions
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
HRESULT
AddMMCPage(
IN LPPROPERTYSHEETCALLBACK lpProvider,
IN CPropertyPage * pg
)
/*++
Routine Description:
Helper function to add MFC property page using callback provider
to MMC.
Arguments:
LPPROPERTYSHEETCALLBACK lpProvider : Property sheet provider
CPropertyPage * pg : MFC property page object
Return Value:
HRESULT
--*/
{
ASSERT(pg != NULL);
//
// Patch MFC property page class.
//
MMCPropPageCallback(&pg->m_psp);
HPROPSHEETPAGE hPage = CreatePropertySheetPage(
(LPCPROPSHEETPAGE)&pg->m_psp
);
if (hPage == NULL)
{
return E_UNEXPECTED;
}
lpProvider->AddPage(hPage);
return S_OK;
}
extern "C" HRESULT APIENTRY
ISMBind(
IN LPCTSTR lpszServer,
OUT HANDLE * phServer
)
/*++
Routine Description:
Generate a handle for the server name.
Arguments:
LPCTSTR lpszServer : Server name
HANDLE * phServer : Returns a handle
Return Value:
HRESULT
--*/
{
return COMDLL_ISMBind(lpszServer, phServer);
}
extern "C" HRESULT APIENTRY
ISMUnbind(
IN HANDLE hServer
)
/*++
Routine Description:
Free up the server handle
Arguments:
HANDLE hServer : Server handle
Return Value:
HRESULT
--*/
{
return COMDLL_ISMUnbind(hServer);
}
extern "C" HRESULT APIENTRY
ISMMMCConfigureServers(
IN HANDLE hServer,
IN PVOID lpfnMMCCallbackProvider,
IN LPARAM param,
IN LONG_PTR handle,
IN DWORD dwInstance
)
/*++
Routine Description:
Display configuration property sheet.
Arguments:
HANDLE hServer : Server handle
PVOID lpfnMMCCallbackProvider : MMC Callback provider
LPARAM param : MMC LPARAM
LONG_PTR handle : MMC Console handle
DWORD dwInstance : Instance number
Return Value:
HRESULT
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CError err;
LPPROPERTYSHEETCALLBACK lpProvider =
(LPPROPERTYSHEETCALLBACK)lpfnMMCCallbackProvider;
LPCTSTR lpszServer = GetServerNameFromHandle(hServer);
ASSERT(lpszServer != NULL);
CString str, strCaption;
LPCTSTR lpszComputer = PURE_COMPUTER_NAME(lpszServer);
if(IS_MASTER_INSTANCE(dwInstance))
{
VERIFY(str.LoadString(IDS_CAPTION_DEFAULT));
strCaption.Format(str, lpszComputer);
}
else
{
VERIFY(str.LoadString(IDS_CAPTION));
strCaption.Format(str, dwInstance, lpszComputer);
}
CFtpSheet * pSheet = NULL;
try
{
pSheet = new CFtpSheet(
strCaption,
lpszServer,
dwInstance,
NULL,
g_cszRoot,
NULL,
param,
handle
);
pSheet->SetModeless();
CFtpServicePage * pServPage = NULL;
CFtpAccountsPage * pAccPage = NULL;
CFtpMessagePage * pMessPage = NULL;
CFtpDirectoryPage * pDirPage = NULL;
CFtpSecurityPage * pSecPage = NULL;
if (SUCCEEDED(pSheet->QueryInstanceResult()))
{
//
// Add instance pages
//
AddMMCPage(lpProvider, new CFtpServicePage(pSheet));
AddMMCPage(lpProvider, new CFtpAccountsPage(pSheet));
AddMMCPage(lpProvider, new CFtpMessagePage(pSheet));
}
if (SUCCEEDED(pSheet->QueryDirectoryResult()))
{
//
// Add home directory pages for the home directory
//
AddMMCPage(lpProvider, new CFtpDirectoryPage(pSheet, TRUE));
AddMMCPage(lpProvider, new CFtpSecurityPage(pSheet));
}
}
catch(CMemoryException * e)
{
TRACEEOLID("Aborting because of exception");
err = ERROR_NOT_ENOUGH_MEMORY;
e->Delete();
}
//
// Sheet and pages clean themselves up
//
return err;
}
extern "C" HRESULT APIENTRY
ISMMMCConfigureChild(
IN HANDLE hServer,
IN PVOID lpfnMMCCallbackProvider,
IN LPARAM param,
IN LONG_PTR handle,
IN DWORD dwAttributes,
IN DWORD dwInstance,
IN LPCTSTR lpszParent,
IN LPCTSTR lpszAlias
)
/*++
Routine Description:
Display configuration property sheet for child object.
Arguments:
HANDLE hServer : Server handle
PVOID lpfnMMCCallbackProvider : MMC Callback provider
LPARAM param : MMC parameter passed to sheet
LONG_PTR handle : MMC console handle
DWORD dwAttributes : Must be FILE_ATTRIBUTE_VIRTUAL_DIRECTORY
DWORD dwInstance : Parent instance number
LPCTSTR lpszParent : Parent path
LPCTSTR lpszAlias : Child to configure
Return Value:
Error return code
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
LPCTSTR lpszServer = GetServerNameFromHandle(hServer);
CError err;
LPPROPERTYSHEETCALLBACK lpProvider =
(LPPROPERTYSHEETCALLBACK)lpfnMMCCallbackProvider;
CString strCaption;
{
CString str;
VERIFY(str.LoadString(IDS_DIR_TITLE));
strCaption.Format(str, lpszAlias);
}
ASSERT(dwAttributes == FILE_ATTRIBUTE_VIRTUAL_DIRECTORY);
//
// Call the APIs and build the property pages
//
CFtpSheet * pSheet = NULL;
try
{
pSheet = new CFtpSheet(
strCaption,
lpszServer,
dwInstance,
lpszParent,
lpszAlias,
NULL,
param,
handle
);
pSheet->SetModeless();
if (SUCCEEDED(pSheet->QueryDirectoryResult()))
{
CFtpDirectoryPage * pDirPage = NULL;
CFtpSecurityPage * pSecPage = NULL;
//
// Add private pages
//
AddMMCPage(lpProvider, new CFtpDirectoryPage(pSheet));
AddMMCPage(lpProvider, new CFtpSecurityPage(pSheet));
}
}
catch(CMemoryException * e)
{
TRACEEOLID("Aborting due to exception");
err = ERROR_NOT_ENOUGH_MEMORY;
e->Delete();
}
//
// Sheet and pages clean themselves up
//
return err;
}
extern "C" HRESULT APIENTRY
ISMEnumerateInstances(
IN HANDLE hServer,
OUT ISMINSTANCEINFO * pii,
OUT IN HANDLE * phEnum
)
/*++
Routine Description:
Enumerate Instances. First call with *phEnum == NULL.
Arguments:
HANDLE hServer : Server handle
ISMINSTANCEINFO * pii : Instance info buffer
HANDLE * phEnum : Enumeration handle.
Return Value:
Error return code
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CError err;
CMetaInterface * pInterface = GetMetaKeyFromHandle(hServer);
ASSERT(pInterface != NULL);
BEGIN_ASSURE_BINDING_SECTION
err = COMDLL_ISMEnumerateInstances(
pInterface,
pii,
phEnum,
g_cszSvc
);
END_ASSURE_BINDING_SECTION(err, pInterface, ERROR_NO_MORE_ITEMS);
return err;
}
extern "C" HRESULT APIENTRY
ISMAddInstance(
IN HANDLE hServer,
IN DWORD dwSourceInstance,
OUT ISMINSTANCEINFO * pii, OPTIONAL
IN DWORD dwBufferSize
)
/*++
Routine Description:
Add an instance.
Arguments:
HANDLE hServer : Server handle
DWORD dwSourceInstance : Source instance ID to clone
ISMINSTANCEINFO * pii : Instance info buffer. May be NULL
DWORD dwBufferSize : Size of buffer
Return Value:
Error return code.
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CIISWizardSheet sheet(IDB_WIZ_LEFT, IDB_WIZ_HEAD);
CIISFtpWizSettings ws(hServer, g_cszSvc);
CIISWizardBookEnd pgWelcome(
IDS_SITE_WELCOME,
IDS_NEW_SITE_WIZARD,
IDS_SITE_BODY
);
CVDWPDescription pgDescr(&ws);
CVDWPBindings pgBindings(&ws);
CVDWPPath pgHome(&ws, FALSE);
CVDWPUserName pgUserName(&ws, FALSE);
CVDWPPermissions pgPerms(&ws, FALSE);
CIISWizardBookEnd pgCompletion(
&ws.m_hrResult,
IDS_SITE_SUCCESS,
IDS_SITE_FAILURE,
IDS_NEW_SITE_WIZARD
);
sheet.AddPage(&pgWelcome);
sheet.AddPage(&pgDescr);
sheet.AddPage(&pgBindings);
sheet.AddPage(&pgHome);
sheet.AddPage(&pgUserName);
sheet.AddPage(&pgPerms);
sheet.AddPage(&pgCompletion);
if (sheet.DoModal() == IDCANCEL)
{
return ERROR_CANCELLED;
}
CError err(ws.m_hrResult);
if (err.Succeeded())
{
//
// Get info on it to be returned.
//
ISMQueryInstanceInfo(
ws.m_pKey,
WITHOUT_INHERITANCE,
pii,
ws.m_dwInstance
);
}
return err;
}
extern "C" HRESULT APIENTRY
ISMDeleteInstance(
IN HANDLE hServer,
IN DWORD dwInstance
)
/*++
Routine Description:
Delete an instance
Arguments:
HANDLE hServer : Server handle
DWORD dwInstance : Instance to be deleted
Return Value:
Error return code.
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CError err;
CMetaInterface * pInterface = GetMetaKeyFromHandle(hServer);
BEGIN_ASSURE_BINDING_SECTION
err = CInstanceProps::Delete(
pInterface,
g_cszSvc,
dwInstance
);
END_ASSURE_BINDING_SECTION(err, pInterface, ERROR_CANCELLED);
return err;
}
extern "C" HRESULT APIENTRY
ISMEnumerateChildren(
IN HANDLE hServer,
OUT ISMCHILDINFO * pii,
OUT IN HANDLE * phEnum,
IN DWORD dwInstance,
IN LPCTSTR lpszParent
)
/*++
Routine Description:
Enumerate children. First call with *phEnum == NULL;
Arguments:
HANDLE hServer : Server handle
ISMCHILDINFO * pii : Child info buffer
HANDLE * phEnum : Enumeration handle.
DWORD dwInstance : Parent instance
LPCTSTR lpszParent : Parent path
Return Value:
Error return code.
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CError err;
CMetaInterface * pInterface = GetMetaKeyFromHandle(hServer);
BEGIN_ASSURE_BINDING_SECTION
err = COMDLL_ISMEnumerateChildren(
pInterface,
pii,
phEnum,
g_cszSvc,
dwInstance,
lpszParent
);
END_ASSURE_BINDING_SECTION(err, pInterface, ERROR_NO_MORE_ITEMS);
return err;
}
extern "C" HRESULT APIENTRY
ISMAddChild(
IN HANDLE hServer,
OUT ISMCHILDINFO * pii,
IN DWORD dwBufferSize,
IN DWORD dwInstance,
IN LPCTSTR lpszParent
)
/*++
Routine Description:
Add a child.
Arguments:
HANDLE hServer : Server handle
ISMCHILDINFO * pii : Child info buffer. May be NULL
DWORD dwBufferSize : Size of info buffer
DWORD dwInstance : Parent instance
LPCTSTR lpszParent : Parent path
Return Value:
Error return code.
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CIISFtpWizSettings ws(hServer, g_cszSvc, dwInstance, lpszParent);
CIISWizardSheet sheet(IDB_WIZ_LEFT_DIR, IDB_WIZ_HEAD_DIR);
CIISWizardBookEnd pgWelcome(
IDS_VDIR_WELCOME,
IDS_NEW_VDIR_WIZARD,
IDS_VDIR_BODY
);
CVDWPAlias pgAlias(&ws);
CVDWPPath pgPath(&ws, TRUE);
CVDWPUserName pgUserName(&ws, TRUE);
CVDWPPermissions pgPerms(&ws, TRUE);
CIISWizardBookEnd pgCompletion(
&ws.m_hrResult,
IDS_VDIR_SUCCESS,
IDS_VDIR_FAILURE,
IDS_NEW_VDIR_WIZARD
);
sheet.AddPage(&pgWelcome);
sheet.AddPage(&pgAlias);
sheet.AddPage(&pgPath);
sheet.AddPage(&pgUserName);
sheet.AddPage(&pgPerms);
sheet.AddPage(&pgCompletion);
if (sheet.DoModal() == IDCANCEL)
{
return ERROR_CANCELLED;
}
CError err(ws.m_hrResult);
if (err.Succeeded())
{
//
// Refresh child info
//
err = ISMQueryChildInfo(
ws.m_pKey,
WITH_INHERITANCE,
pii,
ws.m_dwInstance,
ws.m_strParent,
ws.m_strAlias
);
}
return err;
}
extern "C" HRESULT APIENTRY
ISMDeleteChild(
IN HANDLE hServer,
IN DWORD dwInstance,
IN LPCTSTR lpszParent,
IN LPCTSTR lpszAlias
)
/*++
Routine Description:
Delete a child.
Arguments:
HANDLE hServer : Server handle
DWORD dwInstance : Parent instance
LPCTSTR lpszParent : Parent path
LPCTSTR lpszAlias : Alias of child to be deleted
Return Value:
Error return code.
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CError err;
CMetaInterface * pInterface = GetMetaKeyFromHandle(hServer);
BEGIN_ASSURE_BINDING_SECTION
err = CChildNodeProps::Delete(
pInterface,
g_cszSvc,
dwInstance,
lpszParent,
lpszAlias
);
END_ASSURE_BINDING_SECTION(err, pInterface, ERROR_CANCELLED);
return err;
}
extern "C" HRESULT APIENTRY
ISMRenameChild(
IN HANDLE hServer,
IN DWORD dwInstance,
IN LPCTSTR lpszParent,
IN LPCTSTR lpszAlias,
IN LPCTSTR lpszNewName
)
/*++
Routine Description:
Rename a child.
Arguments:
HANDLE hServer : Server handle
DWORD dwInstance : Parent instance
LPCTSTR lpszParent : Parent path
LPCTSTR lpszAlias : Alias of child to be renamed
LPCTSTR lpszNewName : New alias name
Return Value:
Error return code.
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CError err;
CMetaInterface * pInterface = GetMetaKeyFromHandle(hServer);
BEGIN_ASSURE_BINDING_SECTION
err = CChildNodeProps::Rename(
pInterface,
g_cszSvc,
dwInstance,
lpszParent,
lpszAlias,
lpszNewName
);
END_ASSURE_BINDING_SECTION(err, pInterface, ERROR_CANCELLED)
return err;
}
extern "C" HRESULT APIENTRY
ISMQueryInstanceInfo(
IN HANDLE hServer,
IN BOOL fInherit,
OUT ISMINSTANCEINFO * pii,
IN DWORD dwInstance
)
/*++
Routine Description:
Get instance specific information.
Arguments:
HANDLE hServer : Server handle
BOOL fInherit : TRUE to inherit, FALSE otherwise
ISMINSTANCEINFO * pii : Instance info buffer
LPCTSTR lpszServer : A single server
DWORD dwInstance : Instance number
Return Value:
Error return code.
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
ASSERT(pii != NULL);
CError err;
CMetaKey * pKey = GetMetaKeyFromHandle(hServer);
BEGIN_ASSURE_BINDING_SECTION
CInstanceProps inst(pKey, g_cszSvc, dwInstance);
err = inst.LoadData();
if (err.Succeeded())
{
pii->dwSize = ISMINSTANCEINFO_SIZE;
inst.FillInstanceInfo(pii);
//
// Get properties on the home directory
//
CChildNodeProps home(
&inst,
g_cszSvc,
dwInstance,
NULL,
g_cszRoot,
fInherit,
TRUE // Path only
);
err = home.LoadData();
home.FillInstanceInfo(pii);
}
END_ASSURE_BINDING_SECTION(err, pKey, err);
return err.Failed() ? err : S_OK;
}
extern "C" HRESULT APIENTRY
ISMQueryChildInfo(
IN HANDLE hServer,
IN BOOL fInherit,
OUT ISMCHILDINFO * pii,
IN DWORD dwInstance,
IN LPCTSTR lpszParent,
IN LPCTSTR lpszAlias
)
/*++
Routine Description:
Get child-specific info.
Arguments:
HANDLE hServer : Server handle
BOOL fInherit : TRUE to inherit, FALSE otherwise
ISMCHILDINFO * pii : Child info buffer
DWORD dwInstance : Parent instance
LPCTSTR lpszParent : Parent Path ("" for root)
LPCTSTR lpszAlias : Alias of child to be deleted
Return Value:
Error return code.
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
//
// Get all the inherited properties
//
CChildNodeProps node(
GetMetaKeyFromHandle(hServer),
g_cszSvc,
dwInstance,
lpszParent,
lpszAlias,
fInherit,
FALSE // Complete information
);
CError err(node.LoadData());
//
// Set the output structure
//
pii->dwSize = ISMCHILDINFO_SIZE;
node.FillChildInfo(pii);
//
// Not supported for FTP
//
ASSERT(!node.IsRedirected());
ASSERT(!*pii->szRedirPath);
ASSERT(!pii->fEnabledApplication);
return err;
}
extern "C" HRESULT APIENTRY
ISMConfigureChild(
IN HANDLE hServer,
IN HWND hWnd,
IN DWORD dwAttributes,
IN DWORD dwInstance,
IN LPCTSTR lpszParent,
IN LPCTSTR lpszAlias
)
/*++
Routine Description:
Configure child.
Arguments:
HANDLE hServer : Server handle
HWND hWnd : Main app window handle
DWORD dwAttributes : File attributes
DWORD dwInstance : Parent instance
LPCTSTR lpszParent : Parent path
LPCTSTR lpszAlias : Child to configure or NULL
Return Value:
Error return code.
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CMetaKey * pKey = GetMetaKeyFromHandle(hServer);
LPCTSTR lpszServer = GetServerNameFromHandle(hServer);
CError err;
CString strCaption;
{
CString str;
VERIFY(str.LoadString(IDS_DIR_TITLE));
strCaption.Format(str, lpszAlias);
}
ASSERT(dwAttributes == FILE_ATTRIBUTE_VIRTUAL_DIRECTORY);
//
// Call the APIs and build the property pages
//
CFtpSheet * pSheet = NULL;
try
{
pSheet = new CFtpSheet(
strCaption,
lpszServer,
dwInstance,
lpszParent,
lpszAlias,
CWnd::FromHandlePermanent(hWnd)
);
pSheet->AddRef();
if (SUCCEEDED(pSheet->QueryDirectoryResult()))
{
CFtpDirectoryPage * pDirPage = NULL;
CFtpSecurityPage * pSecPage = NULL;
//
// Add private pages
//
pSheet->AddPage(new CFtpDirectoryPage(pSheet));
pSheet->AddPage(new CFtpSecurityPage(pSheet));
}
}
catch(CMemoryException * e)
{
TRACEEOLID("Aborting due to exception");
err = ERROR_NOT_ENOUGH_MEMORY;
e->Delete();
}
if (err.Succeeded())
{
ASSERT(pSheet != NULL);
pSheet->DoModal();
pSheet->Release();
}
//
// Sheet and pages clean themselves up
//
return err;
}
class CFTPSecurityTemplate : public CIISSecurityTemplate
/*++
Class Description:
FTP Security template class
Public Interface:
CFTPSecurityTemplate : Constructor
ApplySettings : Apply template to destination path
GenerateSummary : Generate text summary
--*/
{
//
// Constructor
//
public:
CFTPSecurityTemplate(
IN const CMetaKey * pKey,
IN LPCTSTR lpszMDPath,
IN BOOL fInherit
);
public:
//
// Apply settings to destination path
//
virtual HRESULT ApplySettings(
IN BOOL fUseTemplates,
IN LPCTSTR lpszServerName,
IN LPCTSTR lpszService,
IN DWORD dwInstance = MASTER_INSTANCE,
IN LPCTSTR lpszParent = NULL,
IN LPCTSTR lpszAlias = NULL
);
//
// Load and parse source data
//
virtual HRESULT LoadData();
virtual void GenerateSummary(
IN BOOL fUseTemplates,
IN LPCTSTR lpszServerName,
IN LPCTSTR lpszService,
IN DWORD dwInstance = MASTER_INSTANCE,
IN LPCTSTR lpszParent = NULL,
IN LPCTSTR lpszAlias = NULL
);
protected:
//
// Break out GetAllData() data to data fields
//
virtual void ParseFields();
public:
MP_BOOL m_fAllowAnonymous;
MP_BOOL m_fAnonymousOnly;
};
CFTPSecurityTemplate::CFTPSecurityTemplate(
IN const CMetaKey * pKey,
IN LPCTSTR lpszMDPath,
IN BOOL fInherit
)
/*++
Routine Description:
Construct from open key
Arguments:
const CMetaKey * pKey : Open key
LPCTSTR lpszMDPath : Path
BOOL fInherit : TRUE to inherit values, FALSE if not
Return Value:
N/A
--*/
: CIISSecurityTemplate(pKey, lpszMDPath, fInherit),
m_fAllowAnonymous(FALSE),
m_fAnonymousOnly(FALSE)
{
//
// Managed Properties
//
m_dlProperties.AddTail(MD_ALLOW_ANONYMOUS);
m_dlProperties.AddTail(MD_ANONYMOUS_ONLY);
}
/* virtual */
HRESULT
CFTPSecurityTemplate::LoadData()
/*++
Routine Description:
LoadData() base class override
Arguments:
None
Return Value:
HRESULT
Notes:
The FTP wizard has an annoying idiosynchrasy: access authentication
settings are per site, not per vdir. Therefore, they need to be set
and fetched in a separate path, and not be set at all if not
setting props on a site. What a pain...
--*/
{
TRACEEOLID(m_strMetaPath);
CError err(CIISSecurityTemplate::LoadData());
if (lstrcmpi(m_strMetaRoot, g_cszRoot) == 0)
{
//
// Fetch the anonymous access settings from
// the instance node. Note: This explicit step
// should only be necessary for templates, because
// this would otherwise be picked up on inheritance.
//
ASSERT(!m_fInherit);
m_strMetaRoot.Empty();
err = CIISSecurityTemplate::LoadData();
}
return err;
}
/* virtual */
void
CFTPSecurityTemplate::ParseFields()
/*++
Routine Description:
Break into fields.
Arguments:
None.
Return Value:
None.
--*/
{
//
// Fetch base class values
//
CIISSecurityTemplate::ParseFields();
BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
HANDLE_META_RECORD(MD_ALLOW_ANONYMOUS, m_fAllowAnonymous)
HANDLE_META_RECORD(MD_ANONYMOUS_ONLY, m_fAnonymousOnly)
END_PARSE_META_RECORDS
}
/* virtual */
HRESULT
CFTPSecurityTemplate::ApplySettings(
IN BOOL fUseTemplate,
IN LPCTSTR lpszServerName,
IN LPCTSTR lpszService,
IN DWORD dwInstance,
IN LPCTSTR lpszParent,
IN LPCTSTR lpszAlias
)
/*++
Routine Description:
Apply the settings to the specified destination path
Arguments:
BOOL fUseTemplates : TRUE if the source is from a template,
FALSE if using inheritance.
LPCTSTR lpszServerName : Server name
LPCTSTR lpszService : Service name
DWORD dwInstance : Instance
LPCTSTR lpszParent : Parent path (or NULL)
LPCTSTR lpszAlias : Alias name (or NULL)
Return Value:
HRESULT
--*/
{
//
// Write base class properties
//
CError err(CIISSecurityTemplate::ApplySettings(
fUseTemplate,
lpszServerName,
lpszService,
dwInstance,
lpszParent,
lpszAlias
));
if (err.Failed())
{
return err;
}
BOOL fWriteProperties = TRUE;
CMetaKey mk(
lpszServerName,
METADATA_PERMISSION_WRITE,
lpszService,
dwInstance,
lpszParent,
lpszAlias
);
err = mk.QueryResult();
if (err.Win32Error() == ERROR_PATH_NOT_FOUND)
{
if (!fUseTemplate)
{
//
// No need to delete properties; everything's already
// inherited. Note that this is the only legit failure
// case. If using a template, the base class must have
// created the path by now.
//
fWriteProperties = FALSE;
err.Reset();
}
}
if (fWriteProperties)
{
do
{
if (mk.IsHomeDirectoryPath())
{
BREAK_ON_ERR_FAILURE(err);
//
// Path describes an instance path, which is the only
// time we need to do anything here
//
err = mk.ConvertToParentPath(TRUE);
BREAK_ON_ERR_FAILURE(err);
if (fUseTemplate)
{
//
// Write values from template
//
err = mk.SetValue(
MD_ALLOW_ANONYMOUS,
m_fAllowAnonymous
);
BREAK_ON_ERR_FAILURE(err);
err = mk.SetValue(
MD_ANONYMOUS_ONLY,
m_fAnonymousOnly
);
}
else
{
//
// Inheritance case: delete authentication
// values
//
mk.DeleteValue(MD_ALLOW_ANONYMOUS);
mk.DeleteValue(MD_ANONYMOUS_ONLY);
}
}
}
while(FALSE);
}
return err;
}
/* virtual */
void
CFTPSecurityTemplate::GenerateSummary(
IN BOOL fUseTemplate,
IN LPCTSTR lpszServerName,
IN LPCTSTR lpszService,
IN DWORD dwInstance,
IN LPCTSTR lpszParent,
IN LPCTSTR lpszAlias
)
/*++
Routine Description:
Generate text summary of what's in the security template, and is about to
be applied to the given path.
Arguments:
BOOL fUseTemplates : TRUE if the source is from a template,
FALSE if using inheritance.
LPCTSTR lpszServerName : Server name
LPCTSTR lpszService : Service name
DWORD dwInstance : Instance
LPCTSTR lpszParent : Parent path (or NULL)
LPCTSTR lpszAlias : Alias name (or NULL)
Return Value:
None
--*/
{
CString strPath;
CMetaKey::BuildMetaPath(
strPath,
lpszService,
dwInstance,
lpszParent,
lpszAlias
);
//
// Authentication methods apply to instances only
//
if (CMetaKey::IsHomeDirectoryPath(strPath))
{
//
// Add private summary items
//
AddSummaryString(IDS_AUTHENTICATION_METHODS);
//
// Summarize Authentication Methods:
//
AddSummaryString(
m_fAllowAnonymous
? IDS_AUTHENTICATION_ANONYMOUS
: IDS_AUTHENTICATION_NO_ANONYMOUS,
1
);
if (m_fAllowAnonymous && m_fAnonymousOnly)
{
AddSummaryString(IDS_AUTHENTICATION_ANONYMOUS_ONLY, 1);
}
}
//
// Add base class summary
//
CIISSecurityTemplate::GenerateSummary(
fUseTemplate,
lpszServerName,
lpszService,
dwInstance,
lpszParent,
lpszAlias
);
}
CIISSecurityTemplate *
AllocateSecurityTemplate(
IN const CMetaKey * pKey,
IN LPCTSTR lpszMDPath,
IN BOOL fInherit
)
/*++
Routine Description:
Security template allocator function
Arguments:
IN const CMetaKey * pKey : Open key
IN LPCTSTR lpszMDPath : Path
IN BOOL fInherit : TRUE to inherit properties
Return Value:
Pointer to newly allocated security object
--*/
{
return new CFTPSecurityTemplate(pKey, lpszMDPath, fInherit);
}
extern "C" HRESULT APIENTRY
ISMSecurityWizard(
IN HANDLE hServer,
IN DWORD dwInstance,
IN LPCTSTR lpszParent,
IN LPCTSTR lpszAlias
)
/*++
Routine Description:
Launch the security wizard
Arguments:
HANDLE hServer : Server handle
DWORD dwInstance : Parent instance
LPCTSTR lpszParent : Parent path
LPCTSTR lpszAlias : Child to configure or NULL
Return Value:
HRESULT
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
return COMDLL_ISMSecurityWizard(
&AllocateSecurityTemplate,
GetMetaKeyFromHandle(hServer),
IDB_WIZ_LEFT_SEC,
IDB_WIZ_HEAD_SEC,
g_cszSvc,
dwInstance,
lpszParent,
lpszAlias
);
}
//
// End of ISM API Functions
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void
InitializeDLL()
/*++
Routine Description:
Perform additional DLL initialisation as necessary
Arguments:
None
Return Value:
None
--*/
{
#ifdef _DEBUG
afxMemDF |= checkAlwaysMemDF;
#endif // _DEBUG
#ifdef UNICODE
TRACEEOLID("Loading UNICODE fscfg.dll");
#else
TRACEEOLID("Loading ANSI fscfg.dll");
#endif UNICODE
::AfxEnableControlContainer();
#ifndef _COMSTATIC
//
// Initialize IISUI extension DLL
//
InitIISUIDll();
#endif // _COMSTATIC
}
//
// Declare the one and only dll object
//
CConfigDll NEAR theApp;
CConfigDll::CConfigDll(
IN LPCTSTR pszAppName OPTIONAL
)
/*++
Routine Description:
Constructor for USRDLL
Arguments:
LPCTSTR pszAppName : Name of the app or NULL to load from resources
Return Value:
N/A
--*/
: CWinApp(pszAppName),
m_lpOldHelpPath(NULL)
{
}
BOOL
CConfigDll::InitInstance()
/*++
Routine Description:
Initialise current instance of the DLL
Arguments:
None
Return Value:
TRUE for successful initialisation, FALSE otherwise
--*/
{
BOOL bInit = CWinApp::InitInstance();
hInstance = ::AfxGetInstanceHandle();
ASSERT(hInstance);
InitializeDLL();
try
{
//
// Get the help path
//
m_lpOldHelpPath = m_pszHelpFilePath;
ASSERT(m_pszHelpFilePath != NULL);
CString strFile(_tcsrchr(m_pszHelpFilePath, _T('\\')));
CRMCRegKey rk(REG_KEY, SZ_PARAMETERS, KEY_READ);
rk.QueryValue(SZ_HELPPATH, m_strHelpPath, EXPANSION_ON);
m_strHelpPath += strFile;
}
catch(CException * e)
{
e->ReportError();
e->Delete();
}
if (!m_strHelpPath.IsEmpty())
{
m_pszHelpFilePath = m_strHelpPath;
}
return bInit;
}
int
CConfigDll::ExitInstance()
/*++
Routine Description:
Clean up current instance
Arguments:
None
Return Value:
The application's exit code; 0 indicates no errors, and values greater
than 0 indicate an error.
--*/
{
m_pszHelpFilePath = m_lpOldHelpPath;
return CWinApp::ExitInstance();
}
//
// Message Map
//
BEGIN_MESSAGE_MAP(CConfigDll, CWinApp)
//{{AFX_MSG_MAP(CConfigDll)
//}}AFX_MSG_MAP
//
// Global Help Commands
//
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
ON_COMMAND(ID_CONTEXT_HELP, CWinApp::OnContextHelp)
END_MESSAGE_MAP()