mirror of https://github.com/tongzx/nt5src
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.
3879 lines
77 KiB
3879 lines
77 KiB
/*++
|
|
|
|
Copyright (c) 1994-1998 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
w3scfg.h
|
|
|
|
Abstract:
|
|
|
|
WWW Configuration Module
|
|
|
|
Author:
|
|
|
|
Ronald Meijer (ronaldm)
|
|
|
|
Project:
|
|
|
|
Internet Services Manager
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
//
|
|
// Include Files
|
|
//
|
|
#include "stdafx.h"
|
|
#include "wincrypt.h"
|
|
|
|
#include <process.h>
|
|
#include <afxtempl.h>
|
|
|
|
|
|
#include "w3scfg.h"
|
|
#include "w3servic.h"
|
|
#include "w3accts.h"
|
|
#include "vdir.h"
|
|
#include "perform.h"
|
|
#include "docum.h"
|
|
#include "security.h"
|
|
#include "httppage.h"
|
|
#include "defws.h"
|
|
#include "fltdlg.h"
|
|
#include "filters.h"
|
|
#include "errors.h"
|
|
#include "wizard.h"
|
|
#include "iisfilt.h"
|
|
#include "..\mmc\constr.h"
|
|
|
|
#define CDELETE(x) {if (x != NULL) delete x;}
|
|
|
|
//
|
|
// Standard configuration Information
|
|
//
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
#define SVC_ID INET_HTTP_SVC_ID
|
|
//
|
|
// Is this server discoverable by INETSLOC?
|
|
//
|
|
#define INETSLOC_DISCOVERY TRUE
|
|
|
|
#if (INETSLOC_DISCOVERY) && !defined(_SVCLOC_)
|
|
#error You must include svcloc.h.
|
|
#endif
|
|
|
|
//
|
|
// If INETSLOC_DISCOVERY == TRUE, define the discovery MASK here.
|
|
//
|
|
#if (INETSLOC_DISCOVERY)
|
|
#define INETSLOC_MASK INET_W3_SVCLOC_ID
|
|
#else // (!INETSLOC_DISCOVERY)
|
|
#define INETSLOC_MASK (ULONGLONG)(0x00000000)
|
|
#endif // (INETSLOC_DISCOVERY)
|
|
|
|
#ifdef NO_SERVICE_CONTROLLER
|
|
#define CAN_CHANGE_SERVICE_STATE FALSE
|
|
#define CAN_PAUSE_SERVICE FALSE
|
|
#else
|
|
//
|
|
// Can we change the service state (start/pause/continue)?
|
|
//
|
|
#define CAN_CHANGE_SERVICE_STATE TRUE
|
|
|
|
//
|
|
// Can we pause this service?
|
|
//
|
|
#define CAN_PAUSE_SERVICE TRUE
|
|
#endif // NO_SERVICE_CONTROLLER
|
|
|
|
//
|
|
// Name used for this service by the service controller manager.
|
|
//
|
|
#define SERVICE_SC_NAME _T("W3Svc")
|
|
|
|
//
|
|
// 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("Web Service")
|
|
|
|
//
|
|
// Web browser protocol name. e.g. xxxxx://address
|
|
// A blank string if this is not supported.
|
|
//
|
|
#define SERVICE_PROTOCOL _T("http")
|
|
|
|
//
|
|
// Use normal colour mapping.
|
|
//
|
|
#define NORMAL_TB_MAPPING TRUE
|
|
|
|
//
|
|
// 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_WWW
|
|
|
|
//
|
|
// Similar to BUTTON_BMP_BACKGROUND, this is the
|
|
// background mask for the service ID
|
|
//
|
|
#define SERVICE_BMP_BACKGROUND RGB(255, 0, 255) // Magenta
|
|
|
|
//
|
|
// Bitmap id which is used in the service view
|
|
// of the service manager. It may be the same
|
|
// bitmap as the BUTTON_BMP_ID bitmap.
|
|
//
|
|
// The bitmap must be 16x16.
|
|
//
|
|
#define SERVICE_BMP_ID IDB_WWW
|
|
|
|
//
|
|
// /* K2 */
|
|
//
|
|
// Similar to BUTTON_BMP_BACKGROUND, this is the
|
|
// background mask for the child bitmap
|
|
//
|
|
#define CHILD_BMP_BACKGROUND RGB(255, 0, 255) // Magenta
|
|
|
|
//
|
|
// /* K2 */
|
|
//
|
|
// Bitmap id which is used for the child
|
|
//
|
|
// The bitmap must be 16x16
|
|
//
|
|
#define CHILD_BMP_ID IDB_WWWVDIR
|
|
|
|
//
|
|
// Large child bitmap ID
|
|
//
|
|
#define CHILD_BMP32_ID IDB_WWWVDIR32
|
|
|
|
//
|
|
// /* K2 */
|
|
//
|
|
// Large bitmap (32x32) id
|
|
//
|
|
#define SERVICE_BMP32_ID IDB_WWW32
|
|
|
|
|
|
//
|
|
// Help IDs
|
|
//
|
|
#define HIDD_DIRECTORY_PROPERTIES (0x207DB)
|
|
#define HIDD_HOME_DIRECTORY_PROPERTIES (HIDD_DIRECTORY_PROPERTIES + 0x20000)
|
|
#define HIDD_FS_DIRECTORY_PROPERTIES (HIDD_DIRECTORY_PROPERTIES + 0x20001)
|
|
#define HIDD_FS_FILE_PROPERTIES (HIDD_DIRECTORY_PROPERTIES + 0x20002)
|
|
|
|
|
|
//
|
|
// Metabase node ID
|
|
//
|
|
const LPCTSTR g_cszSvc = _T("W3SVC");
|
|
const LPCTSTR g_cszFilters = _T("Filters");
|
|
const LPCTSTR g_cszSSLKeys = _T("SSLKeys");
|
|
|
|
|
|
|
|
//
|
|
// End Of Standard configuration Information
|
|
//
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
CW3InstanceProps::CW3InstanceProps(
|
|
IN LPCTSTR lpszServerName,
|
|
IN DWORD dwInstance OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for WWW instance properties
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszServerName : Server name
|
|
DWORD dwInstance : Instance number (could be MASTER_INSTANCE)
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
: CInstanceProps(lpszServerName, g_cszSvc, dwInstance, 80U),
|
|
/**/
|
|
m_nMaxConnections(INITIAL_MAX_CONNECTIONS),
|
|
m_nConnectionTimeOut((LONG)900L),
|
|
m_strlSecureBindings(),
|
|
m_dwLogType(MD_LOG_TYPE_DISABLED),
|
|
/**/
|
|
m_fUseKeepAlives(TRUE),
|
|
m_fEnableCPUAccounting(FALSE),
|
|
m_nServerSize(MD_SERVER_SIZE_MEDIUM),
|
|
m_nMaxNetworkUse(INFINITE_BANDWIDTH),
|
|
/**/
|
|
m_dwCPULimitLogEventRaw(INFINITE_CPU_RAW),
|
|
m_dwCPULimitPriorityRaw(0),
|
|
m_dwCPULimitPauseRaw(0),
|
|
m_dwCPULimitProcStopRaw(0),
|
|
/**/
|
|
m_acl(),
|
|
/**/
|
|
m_dwDownlevelInstance(1),
|
|
m_CertHash()
|
|
{
|
|
//
|
|
// Fetch everything
|
|
//
|
|
m_dwMDUserType = ALL_METADATA;
|
|
m_dwMDDataType = ALL_METADATA;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
void
|
|
CW3InstanceProps::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_SECURE_BINDINGS, m_strlSecureBindings)
|
|
HANDLE_META_RECORD(MD_LOG_TYPE, m_dwLogType)
|
|
//
|
|
// Performance Page
|
|
//
|
|
HANDLE_META_RECORD(MD_SERVER_SIZE, m_nServerSize)
|
|
HANDLE_META_RECORD(MD_ALLOW_KEEPALIVES, m_fUseKeepAlives)
|
|
HANDLE_META_RECORD(MD_MAX_BANDWIDTH, m_nMaxNetworkUse)
|
|
HANDLE_META_RECORD(MD_CPU_LIMITS_ENABLED, m_fEnableCPUAccounting)
|
|
HANDLE_META_RECORD(MD_CPU_LIMIT_LOGEVENT, m_dwCPULimitLogEventRaw)
|
|
HANDLE_META_RECORD(MD_CPU_LIMIT_PRIORITY, m_dwCPULimitPriorityRaw)
|
|
HANDLE_META_RECORD(MD_CPU_LIMIT_PAUSE, m_dwCPULimitPauseRaw)
|
|
HANDLE_META_RECORD(MD_CPU_LIMIT_PROCSTOP, m_dwCPULimitProcStopRaw)
|
|
//
|
|
// Operators Page
|
|
//
|
|
HANDLE_META_RECORD(MD_ADMIN_ACL, m_acl)
|
|
|
|
//
|
|
// Certificate and CTL information
|
|
//
|
|
HANDLE_META_RECORD(MD_SSL_CERT_HASH, m_CertHash)
|
|
HANDLE_META_RECORD(MD_SSL_CERT_STORE_NAME, m_strCertStoreName)
|
|
HANDLE_META_RECORD(MD_SSL_CTL_IDENTIFIER, m_strCTLIdentifier)
|
|
HANDLE_META_RECORD(MD_SSL_CTL_STORE_NAME, m_strCTLStoreName)
|
|
END_PARSE_META_RECORDS
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CW3InstanceProps::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_SECURE_BINDINGS, m_strlSecureBindings)
|
|
META_WRITE(MD_LOG_TYPE, m_dwLogType)
|
|
//
|
|
// Performance Page
|
|
//
|
|
META_WRITE(MD_SERVER_SIZE, m_nServerSize)
|
|
META_WRITE(MD_ALLOW_KEEPALIVES, m_fUseKeepAlives)
|
|
META_WRITE(MD_MAX_BANDWIDTH, m_nMaxNetworkUse)
|
|
META_WRITE(MD_CPU_LIMITS_ENABLED, m_fEnableCPUAccounting)
|
|
META_WRITE(MD_CPU_LIMIT_LOGEVENT, m_dwCPULimitLogEventRaw)
|
|
META_WRITE(MD_CPU_LIMIT_PRIORITY, m_dwCPULimitPriorityRaw)
|
|
META_WRITE(MD_CPU_LIMIT_PAUSE, m_dwCPULimitPauseRaw)
|
|
META_WRITE(MD_CPU_LIMIT_PROCSTOP, m_dwCPULimitProcStopRaw)
|
|
//
|
|
// Operators Page
|
|
//
|
|
META_WRITE(MD_ADMIN_ACL, m_acl)
|
|
|
|
//
|
|
// Certificate and CTL information
|
|
//
|
|
//META_WRITE(MD_SSL_CERT_HASH, m_CertHash)
|
|
//META_WRITE(MD_SSL_CERT_STORE_NAME, m_strCertStoreName)
|
|
META_WRITE(MD_SSL_CTL_IDENTIFIER, m_strCTLIdentifier)
|
|
META_WRITE(MD_SSL_CTL_STORE_NAME, m_strCTLStoreName)
|
|
END_META_WRITE(err);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
CW3DirProps::CW3DirProps(
|
|
IN LPCTSTR lpszServerName,
|
|
IN DWORD dwInstance, OPTIONAL
|
|
IN LPCTSTR lpszParent, OPTIONAL
|
|
IN LPCTSTR lpszAlias OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
WWW Directory Properties Constructor
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszServerName : Server Name
|
|
DWORD dwInstance : Instance number (could be MASTER_INSTANCE)
|
|
LPCTSTR lpszParent : Parent path (could be NULL or "")
|
|
LPCTSTR lpszAlias : Alias name (could be NULL or "")
|
|
|
|
--*/
|
|
: CChildNodeProps(
|
|
lpszServerName,
|
|
g_cszSvc,
|
|
dwInstance,
|
|
lpszParent,
|
|
lpszAlias,
|
|
WITH_INHERITANCE,
|
|
FALSE // Full information
|
|
),
|
|
/**/
|
|
m_strUserName(),
|
|
m_strPassword(),
|
|
m_strDefaultDocument(),
|
|
m_strFooter(),
|
|
m_dwDirBrowsing(0L),
|
|
m_fEnableFooter(FALSE),
|
|
m_fDontLog(FALSE),
|
|
m_fIndexed(FALSE),
|
|
/**/
|
|
m_strExpiration(),
|
|
m_strlCustomHeaders(),
|
|
/**/
|
|
m_strlCustomErrors(),
|
|
/**/
|
|
m_strAnonUserName(),
|
|
m_strAnonPassword(),
|
|
m_fPasswordSync(TRUE),
|
|
m_fU2Installed(FALSE),
|
|
m_fUseNTMapper(FALSE),
|
|
m_dwAuthFlags(MD_AUTH_ANONYMOUS),
|
|
m_dwSSLAccessPermissions(0L),
|
|
m_strBasicDomain(),
|
|
m_ipl()
|
|
{
|
|
//
|
|
// Fetch everything
|
|
//
|
|
m_dwMDUserType = ALL_METADATA;
|
|
m_dwMDDataType = ALL_METADATA;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
void
|
|
CW3DirProps::ParseFields()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Break into fields.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Fetch base properties
|
|
//
|
|
CChildNodeProps::ParseFields();
|
|
|
|
BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
|
|
//
|
|
// VDir Page
|
|
//
|
|
HANDLE_META_RECORD(MD_VR_USERNAME, m_strUserName)
|
|
HANDLE_META_RECORD(MD_VR_PASSWORD, m_strPassword)
|
|
HANDLE_META_RECORD(MD_DEFAULT_LOAD_FILE, m_strDefaultDocument);
|
|
HANDLE_META_RECORD(MD_FOOTER_ENABLED, m_fEnableFooter);
|
|
HANDLE_META_RECORD(MD_FOOTER_DOCUMENT, m_strFooter);
|
|
HANDLE_META_RECORD(MD_DIRECTORY_BROWSING, m_dwDirBrowsing);
|
|
HANDLE_META_RECORD(MD_DONT_LOG, m_fDontLog);
|
|
HANDLE_META_RECORD(MD_IS_CONTENT_INDEXED, m_fIndexed);
|
|
//
|
|
// HTTP Page
|
|
//
|
|
HANDLE_META_RECORD(MD_HTTP_EXPIRES, m_strExpiration);
|
|
HANDLE_META_RECORD(MD_HTTP_CUSTOM, m_strlCustomHeaders);
|
|
//
|
|
// Custom Errors
|
|
//
|
|
HANDLE_META_RECORD(MD_CUSTOM_ERROR, m_strlCustomErrors);
|
|
//
|
|
// Security page
|
|
//
|
|
HANDLE_META_RECORD(MD_AUTHORIZATION, m_dwAuthFlags);
|
|
HANDLE_META_RECORD(MD_SSL_ACCESS_PERM, m_dwSSLAccessPermissions);
|
|
HANDLE_META_RECORD(MD_DEFAULT_LOGON_DOMAIN, m_strBasicDomain);
|
|
HANDLE_META_RECORD(MD_ANONYMOUS_USER_NAME, m_strAnonUserName)
|
|
HANDLE_META_RECORD(MD_ANONYMOUS_PWD, m_strAnonPassword)
|
|
HANDLE_META_RECORD(MD_ANONYMOUS_USE_SUBAUTH, m_fPasswordSync)
|
|
HANDLE_META_RECORD(MD_U2_AUTH, m_fU2Installed)
|
|
HANDLE_META_RECORD(MD_SSL_USE_DS_MAPPER, m_fUseNTMapper);
|
|
HANDLE_META_RECORD(MD_IP_SEC, m_ipl);
|
|
END_PARSE_META_RECORDS
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CW3DirProps::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()
|
|
//
|
|
// VDir Page
|
|
//
|
|
META_WRITE(MD_VR_USERNAME, m_strUserName)
|
|
META_WRITE(MD_VR_PASSWORD, m_strPassword)
|
|
META_WRITE(MD_DEFAULT_LOAD_FILE, m_strDefaultDocument)
|
|
META_WRITE(MD_FOOTER_ENABLED, m_fEnableFooter)
|
|
META_WRITE(MD_FOOTER_DOCUMENT, m_strFooter)
|
|
META_WRITE(MD_DIRECTORY_BROWSING, m_dwDirBrowsing)
|
|
META_WRITE(MD_DONT_LOG, m_fDontLog)
|
|
META_WRITE(MD_IS_CONTENT_INDEXED, m_fIndexed)
|
|
//
|
|
// HTTP Page
|
|
//
|
|
META_WRITE(MD_HTTP_EXPIRES, m_strExpiration)
|
|
META_WRITE(MD_HTTP_CUSTOM, m_strlCustomHeaders)
|
|
//
|
|
// Custom Errors
|
|
//
|
|
META_WRITE(MD_CUSTOM_ERROR, m_strlCustomErrors)
|
|
//
|
|
// Security page
|
|
//
|
|
META_WRITE(MD_AUTHORIZATION, m_dwAuthFlags)
|
|
META_WRITE(MD_SSL_ACCESS_PERM, m_dwSSLAccessPermissions)
|
|
META_WRITE(MD_DEFAULT_LOGON_DOMAIN, m_strBasicDomain)
|
|
META_WRITE(MD_ANONYMOUS_USER_NAME, m_strAnonUserName)
|
|
META_WRITE(MD_ANONYMOUS_PWD, m_strAnonPassword)
|
|
META_WRITE(MD_ANONYMOUS_USE_SUBAUTH, m_fPasswordSync)
|
|
META_WRITE(MD_SSL_USE_DS_MAPPER, m_fUseNTMapper)
|
|
META_WRITE(MD_IP_SEC, m_ipl)
|
|
END_META_WRITE(err);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
CIISFilter::CIISFilter()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Filter contructor for a new filter
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: CObjectPlus(),
|
|
m_strName(),
|
|
|
|
//
|
|
// Default Values
|
|
//
|
|
m_strExecutable(),
|
|
m_nPriority(FLTR_PR_INVALID),
|
|
m_nOrder(-1),
|
|
m_dwState(MD_FILTER_STATE_UNLOADED),
|
|
m_dwFlags(0L),
|
|
m_hrResult(S_OK),
|
|
m_dwWin32Error(ERROR_SUCCESS),
|
|
m_fEnabled(TRUE),
|
|
m_fDirty(FALSE),
|
|
m_fFlaggedForDeletion(FALSE)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
CIISFilter::CIISFilter(
|
|
IN CMetaKey * pKey,
|
|
IN LPCTSTR lpszName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Fully defined constructor
|
|
|
|
Arguments:
|
|
|
|
CMetaKey * pKey : Open key to read from
|
|
LPCTSTR lpszName : Name of the filter
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: m_strName(lpszName),
|
|
//
|
|
// Default Values
|
|
//
|
|
m_strExecutable(),
|
|
m_nPriority(FLTR_PR_INVALID),
|
|
m_nOrder(-1),
|
|
m_dwState(MD_FILTER_STATE_UNLOADED),
|
|
m_dwFlags(0L),
|
|
m_hrResult(S_OK),
|
|
m_dwWin32Error(ERROR_SUCCESS),
|
|
m_fEnabled(TRUE),
|
|
m_fDirty(FALSE),
|
|
m_fFlaggedForDeletion(FALSE)
|
|
{
|
|
ASSERT(pKey != NULL);
|
|
|
|
m_hrResult = pKey->QueryValue(
|
|
MD_FILTER_IMAGE_PATH,
|
|
m_strExecutable,
|
|
NULL,
|
|
m_strName
|
|
);
|
|
|
|
pKey->QueryValue(MD_FILTER_ENABLED, m_fEnabled, NULL, m_strName);
|
|
pKey->QueryValue(MD_FILTER_STATE, m_dwState, NULL, m_strName);
|
|
pKey->QueryValue(MD_FILTER_FLAGS, m_dwFlags, NULL, m_strName);
|
|
|
|
if (m_dwFlags & SF_NOTIFY_ORDER_HIGH)
|
|
{
|
|
m_nPriority = FLTR_PR_HIGH;
|
|
}
|
|
else if (m_dwFlags & SF_NOTIFY_ORDER_MEDIUM)
|
|
{
|
|
m_nPriority = FLTR_PR_MEDIUM;
|
|
}
|
|
else if (m_dwFlags & SF_NOTIFY_ORDER_LOW)
|
|
{
|
|
m_nPriority = FLTR_PR_LOW;
|
|
}
|
|
else
|
|
{
|
|
m_nPriority = FLTR_PR_INVALID;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
CIISFilter::CIISFilter(
|
|
IN const CIISFilter & flt
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy Constructor
|
|
|
|
Arguments:
|
|
|
|
const CIISFilter & flt : Source filter object
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: m_strName(flt.m_strName),
|
|
m_strExecutable(flt.m_strExecutable),
|
|
m_nPriority(flt.m_nPriority),
|
|
m_nOrder(flt.m_nOrder),
|
|
m_hrResult(flt.m_hrResult),
|
|
m_dwState(flt.m_dwState),
|
|
m_dwFlags(flt.m_dwFlags),
|
|
m_dwWin32Error(flt.m_dwWin32Error),
|
|
m_fEnabled(flt.m_fEnabled),
|
|
m_fDirty(FALSE),
|
|
m_fFlaggedForDeletion(FALSE)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISFilter::Write(
|
|
IN CMetaKey * pKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write the current value to the metabase
|
|
|
|
Arguments:
|
|
|
|
CMetaKey * pKey : Open key
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
ASSERT(pKey != NULL);
|
|
|
|
CError err;
|
|
|
|
CString strKey(_T("IIsFilter"));
|
|
err = pKey->SetValue(MD_KEY_TYPE, strKey, NULL, QueryName());
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
err = pKey->SetValue(
|
|
MD_FILTER_IMAGE_PATH,
|
|
m_strExecutable,
|
|
NULL,
|
|
QueryName()
|
|
);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
CIISFilter::OrderByPriority(
|
|
IN const CObjectPlus * pobAccess
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare two filters against each other, and sort on priority first, and
|
|
order secondarily.
|
|
|
|
Arguments:
|
|
|
|
const CObjectPlus * pobAccess : This really refers to another
|
|
CIISFilter to be compared to.
|
|
|
|
Return Value:
|
|
|
|
Sort (+1, 0, -1) return value
|
|
|
|
--*/
|
|
{
|
|
const CIISFilter * pob = (CIISFilter *)pobAccess;
|
|
|
|
if (pob->m_nPriority != m_nPriority)
|
|
{
|
|
return pob->m_nPriority - m_nPriority;
|
|
}
|
|
|
|
//
|
|
// Sort by order in reverse order
|
|
//
|
|
return m_nOrder - pob->m_nOrder;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Static initialization
|
|
//
|
|
const LPCTSTR CIISFilterList::s_lpszSep = _T(",");
|
|
|
|
|
|
|
|
CIISFilterList::CIISFilterList(
|
|
IN LPCTSTR lpszServerName,
|
|
IN LPCTSTR lpszService,
|
|
IN DWORD dwInstance OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for filter list
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszServerName : Server name
|
|
DWORD dwInstance : Instance number (could be MASTER_INSTANCE)
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: CMetaKey(
|
|
lpszServerName,
|
|
METADATA_PERMISSION_READ,
|
|
lpszService,
|
|
dwInstance,
|
|
g_cszFilters
|
|
),
|
|
m_dwInstance(dwInstance),
|
|
m_hrResult(S_OK),
|
|
//
|
|
// Default properties
|
|
//
|
|
m_strFilterOrder(),
|
|
m_fFiltersLoaded(FALSE)
|
|
{
|
|
m_hrResult = CMetaKey::QueryResult();
|
|
|
|
if (SUCCEEDED(m_hrResult))
|
|
{
|
|
m_hrResult = QueryValue(MD_FILTER_LOAD_ORDER, m_strFilterOrder);
|
|
}
|
|
|
|
if (m_hrResult == CError::HResult(ERROR_PATH_NOT_FOUND))
|
|
{
|
|
//
|
|
// Harmless
|
|
//
|
|
m_hrResult = S_OK;
|
|
}
|
|
|
|
if (IsOpen())
|
|
{
|
|
Close();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISFilterList::LoadAllFilters()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Loop through the filter order string, and load information
|
|
about each filter in turn.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
HRESULT. The first error stops filter loading.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(SUCCEEDED(m_hrResult));
|
|
|
|
if (m_fFiltersLoaded)
|
|
{
|
|
//
|
|
// Already done
|
|
//
|
|
return S_OK;
|
|
}
|
|
|
|
int cItems = 0;
|
|
CError err(ReOpen(METADATA_PERMISSION_READ));
|
|
|
|
if (err.Failed())
|
|
{
|
|
return err;
|
|
}
|
|
|
|
try
|
|
{
|
|
CString strSrc(m_strFilterOrder);
|
|
LPTSTR lp = strSrc.GetBuffer(0);
|
|
lp = StringTok(lp, s_lpszSep);
|
|
|
|
int nOrder = 0;
|
|
|
|
while (lp)
|
|
{
|
|
CString str(lp);
|
|
str.TrimLeft();
|
|
str.TrimRight();
|
|
|
|
TRACEEOLID("Adding filter: " << str);
|
|
|
|
CIISFilter * pFilter = new CIISFilter(this, str);
|
|
err = pFilter->QueryResult();
|
|
|
|
if (err.Failed())
|
|
{
|
|
break;
|
|
}
|
|
|
|
pFilter->m_nOrder = nOrder++;
|
|
m_oblFilters.AddTail(pFilter);
|
|
|
|
lp = StringTok(NULL, s_lpszSep);
|
|
++cItems;
|
|
}
|
|
|
|
//
|
|
// Sort filters list
|
|
//
|
|
m_oblFilters.Sort(
|
|
(CObjectPlus::PCOBJPLUS_ORDER_FUNC)
|
|
&CIISFilter::OrderByPriority
|
|
);
|
|
}
|
|
catch(CMemoryException * e)
|
|
{
|
|
e->Delete();
|
|
err = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
m_fFiltersLoaded = err.Succeeded();
|
|
|
|
if (IsOpen())
|
|
{
|
|
Close();
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISFilterList::WriteIfDirty()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write all the changes in the filters list to the metabase
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CError err;
|
|
|
|
CString strNewOrder;
|
|
VERIFY(BuildFilterOrderString(strNewOrder));
|
|
|
|
//
|
|
// Check to see if this new list is different
|
|
//
|
|
if (!strNewOrder.CompareNoCase(m_strFilterOrder) && !HasDirtyFilter())
|
|
{
|
|
//
|
|
// The priority list hasn't changed, and no filter is marked
|
|
// as dirty, so all done.
|
|
//
|
|
return err;
|
|
}
|
|
|
|
//
|
|
// It's dirty -- save it
|
|
//
|
|
do
|
|
{
|
|
err = ReOpen(METADATA_PERMISSION_WRITE);
|
|
|
|
if (err.Failed())
|
|
{
|
|
if (err.Win32Error() == ERROR_PATH_NOT_FOUND)
|
|
{
|
|
//
|
|
// Path didn't exist yet, create it and reopen
|
|
// it.
|
|
//
|
|
err = CreatePathFromFailedOpen();
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
err = ReOpen(METADATA_PERMISSION_WRITE);
|
|
}
|
|
}
|
|
|
|
if (err.Failed())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Delete deleted filters
|
|
//
|
|
POSITION pos1, pos2;
|
|
|
|
for (pos1 = m_oblFilters.GetHeadPosition(); (pos2 = pos1) != NULL; )
|
|
{
|
|
CIISFilter * pFilter = (CIISFilter *)m_oblFilters.GetNext(pos1);
|
|
ASSERT(pFilter != NULL);
|
|
|
|
if (pFilter->IsFlaggedForDeletion())
|
|
{
|
|
TRACEEOLID("Deleting filter " << pFilter->QueryName());
|
|
err = DeleteKey(pFilter->QueryName());
|
|
|
|
if (err.Failed())
|
|
{
|
|
break;
|
|
}
|
|
|
|
m_oblFilters.RemoveAt(pos2);
|
|
}
|
|
}
|
|
|
|
if (err.Failed())
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Two passes are necessary, because the filter may
|
|
// have been re-added after it was deleted from the
|
|
// list as new entry. This could be somewhat improved
|
|
//
|
|
ResetEnumerator();
|
|
|
|
while(MoreFilters())
|
|
{
|
|
CIISFilter * pFilter = GetNextFilter();
|
|
ASSERT(pFilter != NULL);
|
|
|
|
if (pFilter->IsDirty())
|
|
{
|
|
TRACEEOLID("Writing filter " << pFilter->QueryName());
|
|
err = pFilter->Write(this);
|
|
|
|
if (err.Failed())
|
|
{
|
|
break;
|
|
}
|
|
|
|
pFilter->Dirty(FALSE);
|
|
}
|
|
}
|
|
|
|
if (err.Failed())
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Write the new filter load order
|
|
//
|
|
err = SetValue(MD_FILTER_LOAD_ORDER, strNewOrder);
|
|
|
|
if (err.Failed())
|
|
{
|
|
break;
|
|
}
|
|
|
|
CString strKey(_T("IIsFilters"));
|
|
err = SetValue(MD_KEY_TYPE, strKey);
|
|
err = SetValue(MD_FILTER_LOAD_ORDER, strNewOrder);
|
|
|
|
m_strFilterOrder = strNewOrder;
|
|
}
|
|
while(FALSE);
|
|
|
|
if (IsOpen())
|
|
{
|
|
Close();
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
POSITION
|
|
CIISFilterList::GetFilterPositionByIndex(
|
|
IN int nSel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the position of a filter object by index, skipping filters
|
|
marked for deletion.
|
|
|
|
Arguments:
|
|
|
|
int nSel - 0 based index into the list
|
|
|
|
Return Value:
|
|
|
|
The POSITION into the filters ObList of the filter at the index
|
|
specified, or NULL if the filter is not found.
|
|
|
|
--*/
|
|
{
|
|
int nIndex = -1;
|
|
CIISFilter * pFilter;
|
|
POSITION pos,
|
|
posReturn = NULL;
|
|
|
|
pos = m_oblFilters.GetHeadPosition();
|
|
|
|
while(pos && nIndex < nSel)
|
|
{
|
|
posReturn = pos;
|
|
pFilter = (CIISFilter *)m_oblFilters.GetNext(pos);
|
|
|
|
//
|
|
// Skipping deleted filters
|
|
//
|
|
if (!pFilter->IsFlaggedForDeletion())
|
|
{
|
|
++nIndex;
|
|
}
|
|
}
|
|
|
|
return posReturn;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CIISFilterList::ExchangePositions(
|
|
IN int nSel1,
|
|
IN int nSel2,
|
|
OUT CIISFilter *& p1,
|
|
OUT CIISFilter *& p2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Exchange the positions of two filters in the list
|
|
|
|
Arguments:
|
|
|
|
int nSel1 : Item 1
|
|
int nSel2 : Item 2
|
|
CIISFilter *& p1 : Returns the item moved to position 1
|
|
CIISFilter *& p2 : Returns the item moved to position 2
|
|
|
|
Return Value:
|
|
|
|
TRUE for success, FALSE for failure.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(SUCCEEDED(m_hrResult));
|
|
|
|
//
|
|
// Fetch filters at the two positions (deleted filters are
|
|
// skipped in the index count)
|
|
//
|
|
POSITION pos1 = GetFilterPositionByIndex(nSel1);
|
|
POSITION pos2 = GetFilterPositionByIndex(nSel2);
|
|
p1 = pos2 ? (CIISFilter *)m_oblFilters.GetAt(pos2) : NULL;
|
|
p2 = pos1 ? (CIISFilter *)m_oblFilters.GetAt(pos1) : NULL;
|
|
|
|
if (!p1 || !p2)
|
|
{
|
|
TRACEEOLID("Invalid internal state -- filter exchange impossible");
|
|
ASSERT(FALSE);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
TRACEEOLID("Filter (1) name is " << p1->m_strName);
|
|
TRACEEOLID("Filter (2) name is " << p2->m_strName);
|
|
|
|
//
|
|
// Exchange
|
|
//
|
|
m_oblFilters.SetAt(pos1, p1);
|
|
m_oblFilters.SetAt(pos2, p2);
|
|
|
|
//
|
|
// Success
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
LPCTSTR
|
|
CIISFilterList::BuildFilterOrderString(
|
|
OUT CString & strFilterOrder
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert the oblist of filters to a single filter order string
|
|
fit to be stuffed into the metabase
|
|
|
|
Arguments:
|
|
|
|
CString & strFilterOrder : Output to receive the order string
|
|
|
|
Return Value:
|
|
|
|
A pointer to the new filter order string.
|
|
|
|
--*/
|
|
{
|
|
BOOL fFirst = TRUE;
|
|
POSITION pos = m_oblFilters.GetHeadPosition();
|
|
|
|
strFilterOrder.Empty();
|
|
|
|
while(pos)
|
|
{
|
|
CIISFilter * pFlt = (CIISFilter *)m_oblFilters.GetNext(pos);
|
|
|
|
if (!pFlt->IsFlaggedForDeletion())
|
|
{
|
|
if (!fFirst)
|
|
{
|
|
strFilterOrder += s_lpszSep;
|
|
}
|
|
else
|
|
{
|
|
fFirst = FALSE;
|
|
}
|
|
|
|
strFilterOrder += pFlt->m_strName;
|
|
}
|
|
}
|
|
|
|
return (LPCTSTR)strFilterOrder;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CIISFilterList::HasDirtyFilter() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Go through the list of filters, and return TRUE if any filter
|
|
in the list is dirty or flagged for deletion
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if any filter is dirty or flagged for deletion.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(SUCCEEDED(m_hrResult));
|
|
|
|
POSITION pos = m_oblFilters.GetHeadPosition();
|
|
|
|
while(pos)
|
|
{
|
|
CIISFilter * pFilter = (CIISFilter *)m_oblFilters.GetNext(pos);
|
|
|
|
if (pFilter->IsFlaggedForDeletion() || pFilter->IsDirty())
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Message Map
|
|
//
|
|
BEGIN_MESSAGE_MAP(CW3Sheet, CInetPropertySheet)
|
|
//{{AFX_MSG_MAP(CInetPropertySheet)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
CW3Sheet::CW3Sheet(
|
|
LPCTSTR pszCaption,
|
|
DWORD dwAttributes,
|
|
LPCTSTR lpszServer,
|
|
DWORD dwInstance,
|
|
LPCTSTR lpszParent,
|
|
LPCTSTR lpszAlias,
|
|
CWnd * pParentWnd,
|
|
LPARAM lParam,
|
|
LONG_PTR handle,
|
|
UINT iSelectPage
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
WWW 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_fNew(FALSE),
|
|
m_dwAttributes(dwAttributes),
|
|
m_ppropInst(NULL),
|
|
m_ppropDir(NULL)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
CW3Sheet::~CW3Sheet()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sheet destructor
|
|
|
|
Arguments:
|
|
|
|
N/A
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
{
|
|
FreeConfigurationParameters();
|
|
|
|
//
|
|
// Must be deleted by now
|
|
//
|
|
ASSERT(m_ppropInst == NULL);
|
|
ASSERT(m_ppropDir == NULL);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CW3Sheet::WinHelp(
|
|
IN DWORD dwData,
|
|
IN UINT nCmd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
WWW 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.
|
|
|
|
--*/
|
|
{
|
|
if (dwData == HIDD_DIRECTORY_PROPERTIES)
|
|
{
|
|
if (IS_FILE(m_dwAttributes))
|
|
{
|
|
dwData = HIDD_FS_FILE_PROPERTIES;
|
|
}
|
|
else if (IS_DIR(m_dwAttributes))
|
|
{
|
|
dwData = HIDD_FS_DIRECTORY_PROPERTIES;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(IS_VROOT(m_dwAttributes));
|
|
ASSERT(m_ppropDir != NULL);
|
|
|
|
if (!::lstrcmpi(m_ppropDir->m_strAlias, g_cszRoot))
|
|
{
|
|
//
|
|
// It's a home virtual directory -- change the ID
|
|
//
|
|
dwData = HIDD_HOME_DIRECTORY_PROPERTIES;
|
|
}
|
|
}
|
|
}
|
|
|
|
CInetPropertySheet::WinHelp(dwData, nCmd);
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CW3Sheet::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 CW3InstanceProps(m_strServer, m_dwInstance);
|
|
m_ppropDir = new CW3DirProps(
|
|
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
|
|
CW3Sheet::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);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Global DLL instance
|
|
//
|
|
HINSTANCE hInstance;
|
|
|
|
|
|
|
|
//
|
|
// ISM API Functions
|
|
//
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
extern "C" DWORD APIENTRY
|
|
ISMQueryServiceInfo(
|
|
OUT ISMSERVICEINFO * psi
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return service-specific information back to 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 value
|
|
|
|
--*/
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState() );
|
|
|
|
ASSERT(psi != NULL);
|
|
ASSERT(psi->dwSize == ISMSERVICEINFO_SIZE);
|
|
|
|
psi->dwSize = ISMSERVICEINFO_SIZE;
|
|
psi->dwVersion = ISM_VERSION;
|
|
|
|
psi->flServiceInfoFlags = 0
|
|
| ISMI_INETSLOCDISCOVER
|
|
| ISMI_CANCONTROLSERVICE
|
|
| ISMI_CANPAUSESERVICE
|
|
| ISMI_UNDERSTANDINSTANCE
|
|
| ISMI_NORMALTBMAPPING
|
|
| ISMI_INSTANCES
|
|
| ISMI_CHILDREN
|
|
| ISMI_FILESYSTEM
|
|
| ISMI_TASKPADS
|
|
| ISMI_SECURITYWIZARD
|
|
| ISMI_HASWEBPROTOCOL
|
|
| ISMI_SUPPORTSMETABASE
|
|
| ISMI_SUPPORTSMASTER
|
|
; /**/
|
|
|
|
ASSERT(::lstrlen(SERVICE_LONG_NAME) <= MAX_LNLEN);
|
|
ASSERT(::lstrlen(SERVICE_SHORT_NAME) <= MAX_SNLEN);
|
|
|
|
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->rgbLargeServiceBkMask = SERVICE_BMP_BACKGROUND;
|
|
psi->nLargeServiceBitmapID = SERVICE_BMP32_ID;
|
|
::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;
|
|
}
|
|
|
|
|
|
|
|
extern "C" DWORD APIENTRY
|
|
ISMDiscoverServers(
|
|
OUT ISMSERVERINFO * psi,
|
|
IN DWORD * pdwBufferSize,
|
|
IN OUT int * cServers
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Discover machines running this service. This is only necessary for
|
|
services not discovered with inetscloc (which don't give a mask)
|
|
|
|
Arguments:
|
|
|
|
ISMSERVERINFO * psi : Server info buffer.
|
|
DWORD * pdwBufferSize : Size required/available.
|
|
OUT 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.Win32Error();
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
{
|
|
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.m_nISMState;
|
|
|
|
return err.Win32Error();
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
DWORD dwAttributes = FILE_ATTRIBUTE_VIRTUAL_DIRECTORY;
|
|
|
|
CW3Sheet * pSheet = NULL;
|
|
|
|
try
|
|
{
|
|
|
|
//
|
|
// Call the APIs and build the property pages
|
|
//
|
|
pSheet = new CW3Sheet(
|
|
strCaption,
|
|
dwAttributes,
|
|
lpszServer,
|
|
dwInstance,
|
|
NULL,
|
|
g_cszRoot,
|
|
CWnd::FromHandlePermanent(hWnd)
|
|
);
|
|
pSheet->AddRef();
|
|
|
|
if (SUCCEEDED(pSheet->QueryInstanceResult()))
|
|
{
|
|
//
|
|
// Add instance pages
|
|
//
|
|
pSheet->AddPage(new CW3ServicePage(pSheet));
|
|
|
|
if (pSheet->cap().HasOperatorList() && pSheet->HasAdminAccess())
|
|
{
|
|
pSheet->AddPage(new CW3AccountsPage(pSheet));
|
|
}
|
|
|
|
pSheet->AddPage(new CW3PerfPage(pSheet));
|
|
pSheet->AddPage(new CW3FiltersPage(pSheet));
|
|
}
|
|
|
|
if (SUCCEEDED(pSheet->QueryDirectoryResult()))
|
|
{
|
|
//
|
|
// Add directory pages
|
|
//
|
|
pSheet->AddPage(new CW3DirectoryPage(pSheet, TRUE));
|
|
pSheet->AddPage(new CW3DocumentsPage(pSheet));
|
|
pSheet->AddPage(new CW3SecurityPage(pSheet, TRUE, dwAttributes));
|
|
pSheet->AddPage(new CW3HTTPPage(pSheet));
|
|
pSheet->AddPage(new CW3ErrorsPage(pSheet));
|
|
}
|
|
|
|
if(dwInstance == MASTER_INSTANCE)
|
|
{
|
|
pSheet->AddPage(new CDefWebSitePage(pSheet));
|
|
}
|
|
}
|
|
catch(CMemoryException * e)
|
|
{
|
|
TRACEEOLID("Aborting due to 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);
|
|
}
|
|
|
|
DWORD dwAttributes = FILE_ATTRIBUTE_VIRTUAL_DIRECTORY;
|
|
|
|
CW3Sheet * pSheet = NULL;
|
|
|
|
try
|
|
{
|
|
//
|
|
// Call the APIs and build the property pages
|
|
//
|
|
pSheet = new CW3Sheet(
|
|
strCaption,
|
|
dwAttributes,
|
|
lpszServer,
|
|
dwInstance,
|
|
NULL,
|
|
g_cszRoot,
|
|
NULL,
|
|
param,
|
|
handle
|
|
);
|
|
|
|
pSheet->SetModeless();
|
|
|
|
if (SUCCEEDED(pSheet->QueryInstanceResult()))
|
|
{
|
|
//
|
|
// Add instance pages
|
|
//
|
|
AddMMCPage(lpProvider, new CW3ServicePage(pSheet));
|
|
|
|
if (pSheet->cap().HasOperatorList() && pSheet->HasAdminAccess())
|
|
{
|
|
AddMMCPage(lpProvider, new CW3AccountsPage(pSheet));
|
|
}
|
|
|
|
AddMMCPage(lpProvider, new CW3PerfPage(pSheet));
|
|
AddMMCPage(lpProvider, new CW3FiltersPage(pSheet));
|
|
}
|
|
|
|
if (SUCCEEDED(pSheet->QueryDirectoryResult()))
|
|
{
|
|
//
|
|
// Add directory pages
|
|
//
|
|
AddMMCPage(lpProvider, new CW3DirectoryPage(pSheet, TRUE));
|
|
AddMMCPage(lpProvider, new CW3DocumentsPage(pSheet));
|
|
AddMMCPage(lpProvider, new CW3SecurityPage(pSheet,TRUE, dwAttributes));
|
|
AddMMCPage(lpProvider, new CW3HTTPPage(pSheet));
|
|
AddMMCPage(lpProvider, new CW3ErrorsPage(pSheet));
|
|
}
|
|
|
|
if(dwInstance == MASTER_INSTANCE)
|
|
{
|
|
AddMMCPage(lpProvider, new CDefWebSitePage(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
|
|
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);
|
|
}
|
|
|
|
CW3Sheet * pSheet = NULL;
|
|
|
|
try
|
|
{
|
|
pSheet = new CW3Sheet(
|
|
strCaption,
|
|
dwAttributes,
|
|
lpszServer,
|
|
dwInstance,
|
|
lpszParent,
|
|
lpszAlias,
|
|
NULL,
|
|
param,
|
|
handle
|
|
);
|
|
|
|
pSheet->SetModeless();
|
|
|
|
//
|
|
// Do not allow editing of a file/dir which is overridden
|
|
// by an alias.
|
|
//
|
|
#pragma message("Warning: file/vroot check stubbed out")
|
|
|
|
/*
|
|
if (!IS_VROOT(dwAttributes)
|
|
&& !pSheet->GetDirectoryProperties().IsPathInherited())
|
|
{
|
|
::AfxMessageBox(IDS_ERR_VROOT_OVERRIDE);
|
|
pSheet->Release();
|
|
|
|
return S_OK;
|
|
}
|
|
*/
|
|
|
|
//
|
|
// Call the APIs and build the property pages
|
|
//
|
|
if (SUCCEEDED(pSheet->QueryDirectoryResult()))
|
|
{
|
|
AddMMCPage(lpProvider, new CW3DirectoryPage(pSheet, FALSE, dwAttributes));
|
|
|
|
if (!IS_FILE(dwAttributes))
|
|
{
|
|
AddMMCPage(lpProvider, new CW3DocumentsPage(pSheet));
|
|
}
|
|
|
|
AddMMCPage(lpProvider, new CW3SecurityPage(pSheet, FALSE, dwAttributes));
|
|
AddMMCPage(lpProvider, new CW3HTTPPage(pSheet));
|
|
AddMMCPage(lpProvider, new CW3ErrorsPage(pSheet));
|
|
}
|
|
}
|
|
catch(CMemoryException * e)
|
|
{
|
|
TRACEEOLID("Aborting due to exception");
|
|
err = ERROR_NOT_ENOUGH_MEMORY;
|
|
e->Delete();
|
|
}
|
|
|
|
//
|
|
// Sheet and pages will delete themselves
|
|
//
|
|
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);
|
|
|
|
CIISWebWizSettings 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 CError::HResult(ERROR_CANCELLED);
|
|
}
|
|
|
|
CError err(ws.m_hrResult);
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
//
|
|
// Get info on it to be returned.
|
|
//
|
|
ISMQueryInstanceInfo(
|
|
hServer,
|
|
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() );
|
|
|
|
CMetaKey * pKey = GetMetaKeyFromHandle(hServer);
|
|
LPCTSTR lpszServer = GetServerNameFromHandle(hServer);
|
|
|
|
//
|
|
// First, attempt to delete the applications that might live
|
|
// here
|
|
//
|
|
CIISApplication app(lpszServer, g_cszSvc, dwInstance, g_cszRoot);
|
|
CError err(app.QueryResult());
|
|
|
|
if(err.Succeeded())
|
|
{
|
|
//
|
|
// Recursively delete all app info
|
|
//
|
|
err = app.DeleteRecoverable(TRUE);
|
|
}
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
BEGIN_ASSURE_BINDING_SECTION
|
|
err = CInstanceProps::Delete(
|
|
pKey,
|
|
g_cszSvc,
|
|
dwInstance
|
|
);
|
|
END_ASSURE_BINDING_SECTION(err, pKey, ERROR_CANCELLED);
|
|
|
|
if (err.Failed())
|
|
{
|
|
//
|
|
// Failed to delete the instance -- recover application
|
|
// information recursively
|
|
//
|
|
app.Recover(TRUE);
|
|
}
|
|
}
|
|
|
|
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);
|
|
ASSERT(pInterface != NULL);
|
|
|
|
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());
|
|
|
|
CIISWizardSheet sheet(IDB_WIZ_LEFT_DIR, IDB_WIZ_HEAD_DIR);
|
|
|
|
CIISWebWizSettings ws(hServer, g_cszSvc, dwInstance, lpszParent);
|
|
|
|
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())
|
|
{
|
|
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());
|
|
|
|
CMetaKey * pKey = GetMetaKeyFromHandle(hServer);
|
|
LPCTSTR lpszServer = GetServerNameFromHandle(hServer);
|
|
ASSERT(lpszServer != NULL);
|
|
|
|
//
|
|
// First, attempt to delete the applications that might live
|
|
// here.
|
|
//
|
|
CIISApplication app(
|
|
lpszServer,
|
|
g_cszSvc,
|
|
dwInstance,
|
|
lpszParent,
|
|
lpszAlias
|
|
);
|
|
|
|
CError err(app.QueryResult());
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
err = app.DeleteRecoverable(TRUE);
|
|
}
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
BEGIN_ASSURE_BINDING_SECTION
|
|
err = CChildNodeProps::Delete(
|
|
pKey,
|
|
g_cszSvc,
|
|
dwInstance,
|
|
lpszParent,
|
|
lpszAlias
|
|
);
|
|
END_ASSURE_BINDING_SECTION(err, pKey, ERROR_CANCELLED);
|
|
|
|
if (err.Failed())
|
|
{
|
|
//
|
|
// Failed to delete the child node -- recover application
|
|
// information
|
|
//
|
|
app.Recover(TRUE);
|
|
}
|
|
}
|
|
|
|
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() );
|
|
|
|
CMetaKey * pKey = GetMetaKeyFromHandle(hServer);
|
|
LPCTSTR lpszServer = GetServerNameFromHandle(hServer);
|
|
ASSERT(lpszServer != NULL);
|
|
|
|
//
|
|
// First, attempt to delete the applications that might live
|
|
// here.
|
|
//
|
|
CIISApplication app(
|
|
lpszServer,
|
|
g_cszSvc,
|
|
dwInstance,
|
|
lpszParent,
|
|
lpszAlias
|
|
);
|
|
|
|
CError err(app.QueryResult());
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
//
|
|
// Delete recursively
|
|
//
|
|
err = app.DeleteRecoverable(TRUE);
|
|
}
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
BEGIN_ASSURE_BINDING_SECTION
|
|
err = CChildNodeProps::Rename(
|
|
pKey,
|
|
g_cszSvc,
|
|
dwInstance,
|
|
lpszParent,
|
|
lpszAlias,
|
|
lpszNewName
|
|
);
|
|
END_ASSURE_BINDING_SECTION(err, pKey, ERROR_CANCELLED);
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
//
|
|
// Rename succeeded -- recover application information
|
|
// on the _new_ metabase path.
|
|
//
|
|
CIISApplication appNew(
|
|
lpszServer,
|
|
g_cszSvc,
|
|
dwInstance,
|
|
lpszParent,
|
|
lpszNewName
|
|
);
|
|
|
|
err = appNew.QueryResult();
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
err = appNew.Recover(TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Failed to delete the child node -- recover application
|
|
// information on the _old_ metabase path (don't disturb the
|
|
// error code).
|
|
//
|
|
app.Recover(TRUE);
|
|
}
|
|
}
|
|
|
|
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())
|
|
{
|
|
//
|
|
// Set the output structure
|
|
//
|
|
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 // Everything
|
|
);
|
|
CError err(node.LoadData());
|
|
|
|
//
|
|
// Set the output structure
|
|
//
|
|
pii->dwSize = ISMCHILDINFO_SIZE;
|
|
node.FillChildInfo(pii);
|
|
|
|
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);
|
|
ASSERT(lpszServer != NULL);
|
|
|
|
CError err;
|
|
|
|
CString strCaption;
|
|
{
|
|
CString str;
|
|
VERIFY(str.LoadString(IDS_DIR_TITLE));
|
|
|
|
strCaption.Format(str, lpszAlias);
|
|
}
|
|
|
|
CW3Sheet * pSheet = NULL;
|
|
|
|
try
|
|
{
|
|
pSheet = new CW3Sheet(
|
|
strCaption,
|
|
dwAttributes,
|
|
lpszServer,
|
|
dwInstance,
|
|
lpszParent,
|
|
lpszAlias,
|
|
CWnd::FromHandlePermanent(hWnd)
|
|
);
|
|
|
|
pSheet->AddRef();
|
|
|
|
//
|
|
// Do not allow editing of a file/dir which is overridden
|
|
// by an alias.
|
|
//
|
|
if (!IS_VROOT(dwAttributes)
|
|
&& !pSheet->GetDirectoryProperties().IsPathInherited())
|
|
{
|
|
::AfxMessageBox(IDS_ERR_VROOT_OVERRIDE);
|
|
pSheet->Release();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Call the APIs and build the property pages
|
|
//
|
|
if (SUCCEEDED(pSheet->QueryDirectoryResult()))
|
|
{
|
|
pSheet->AddPage(new CW3DirectoryPage(pSheet, FALSE, dwAttributes));
|
|
|
|
if (!IS_FILE(dwAttributes))
|
|
{
|
|
pSheet->AddPage(new CW3DocumentsPage(pSheet));
|
|
}
|
|
|
|
pSheet->AddPage(new CW3SecurityPage(pSheet, FALSE, dwAttributes));
|
|
pSheet->AddPage(new CW3HTTPPage(pSheet));
|
|
pSheet->AddPage(new CW3ErrorsPage(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 will delete themselves
|
|
//
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Authentication bit strings
|
|
//
|
|
FLAGTOSTRING fsAuthentications[] =
|
|
{
|
|
{ MD_AUTH_ANONYMOUS, IDS_AUTHENTICATION_ANONYMOUS, TRUE },
|
|
{ MD_AUTH_ANONYMOUS, IDS_AUTHENTICATION_NO_ANONYMOUS, FALSE },
|
|
{ MD_AUTH_BASIC, IDS_AUTHENTICATION_BASIC, TRUE },
|
|
{ MD_AUTH_MD5, IDS_AUTHENTICATION_DIGEST, TRUE },
|
|
{ MD_AUTH_NT, IDS_AUTHENTICATION_NT, TRUE },
|
|
};
|
|
|
|
|
|
|
|
class CWebSecurityTemplate : public CIISSecurityTemplate
|
|
/*++
|
|
|
|
Class Description:
|
|
|
|
Web Security template class
|
|
|
|
Public Interface:
|
|
|
|
CWebSecurityTemplate : Constructor
|
|
|
|
ApplySettings : Apply template to destination path
|
|
GenerateSummary : Generate text summary
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Constructor
|
|
//
|
|
public:
|
|
CWebSecurityTemplate(
|
|
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
|
|
);
|
|
|
|
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_DWORD m_dwAuthentication;
|
|
MP_DWORD m_dwDirBrowsing;
|
|
};
|
|
|
|
|
|
|
|
CWebSecurityTemplate::CWebSecurityTemplate(
|
|
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_dwAuthentication(MD_AUTH_ANONYMOUS),
|
|
m_dwDirBrowsing(
|
|
MD_DIRBROW_SHOW_DATE |
|
|
MD_DIRBROW_SHOW_TIME |
|
|
MD_DIRBROW_SHOW_SIZE |
|
|
MD_DIRBROW_SHOW_EXTENSION
|
|
)
|
|
{
|
|
//
|
|
// Managed Properties
|
|
//
|
|
m_dlProperties.AddTail(MD_AUTHORIZATION);
|
|
// m_dlProperties.AddTail(MD_DIRECTORY_BROWSING); // out of IIS 5
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
void
|
|
CWebSecurityTemplate::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_AUTHORIZATION, m_dwAuthentication)
|
|
//HANDLE_META_RECORD(MD_DIRECTORY_BROWSING, m_dwDirBrowsing) // Out of IIS 5
|
|
END_PARSE_META_RECORDS
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CWebSecurityTemplate::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
|
|
{
|
|
BREAK_ON_ERR_FAILURE(err);
|
|
|
|
if (fUseTemplate)
|
|
{
|
|
//
|
|
// Write values from template
|
|
//
|
|
err = mk.SetValue(
|
|
MD_AUTHORIZATION,
|
|
m_dwAuthentication
|
|
);
|
|
|
|
BREAK_ON_ERR_FAILURE(err);
|
|
|
|
//
|
|
// dir browsing out of iis 5
|
|
//
|
|
/*
|
|
err = mk.SetValue(
|
|
MD_DIRECTORY_BROWSING,
|
|
m_dwDirBrowsing
|
|
);
|
|
BREAK_ON_ERR_FAILURE(err);
|
|
*/
|
|
}
|
|
|
|
//
|
|
// Nothing to do in the inheritance case, because the
|
|
// base class knows which properties should be deleted
|
|
//
|
|
}
|
|
while(FALSE);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
void
|
|
CWebSecurityTemplate::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. Arguments are
|
|
the same as ApplySettings(), so that the summary can reflect what will
|
|
actually be set.
|
|
|
|
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
|
|
--*/
|
|
{
|
|
AddSummaryString(IDS_AUTHENTICATION_METHODS);
|
|
|
|
int i;
|
|
|
|
//
|
|
// Summarize Authentication Methods:
|
|
//
|
|
if (m_dwAuthentication == 0L)
|
|
{
|
|
AddSummaryString(IDS_SUMMARY_NONE, 1);
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < ARRAY_SIZE(fsAuthentications); ++i)
|
|
{
|
|
if (IS_FLAG_SET(
|
|
m_dwAuthentication,
|
|
fsAuthentications[i].dwFlag
|
|
) == fsAuthentications[i].fSet)
|
|
{
|
|
AddSummaryString(fsAuthentications[i].nID, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// CODEWORK: Dir browsing settings in the security wizards are postponed
|
|
// to post IIS 5
|
|
//
|
|
/*
|
|
if (IS_FLAG_SET(m_dwDirBrowsing, MD_DIRBROW_ENABLED))
|
|
{
|
|
AddSummaryString(IDS_DIR_BROWSE_ON, 1);
|
|
}
|
|
else
|
|
{
|
|
AddSummaryString(IDS_DIR_BROWSE_OFF, 1);
|
|
}
|
|
|
|
if (IS_FLAG_SET(m_dwDirBrowsing, MD_DIRBROW_LOADDEFAULT))
|
|
{
|
|
AddSummaryString(IDS_LOAD_DEFAULT_ON, 1);
|
|
}
|
|
else
|
|
{
|
|
AddSummaryString(IDS_LOAD_DEFAULT_OFF, 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 CWebSecurityTemplate(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
|
|
//
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
DWORD
|
|
IsSSLEnabledOnServer(
|
|
IN LPCTSTR lpszServer,
|
|
OUT BOOL & fInstalled,
|
|
OUT BOOL & fEnabled
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine if SSL is installed on the server.
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszServer : Server name
|
|
BOOL & fInstalled : Returns TRUE if SSL is installed
|
|
BOOL & fEnabled : Returns TRUE if SSL is enabled
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
|
|
--*/
|
|
{
|
|
/*
|
|
LPW3_CONFIG_INFO lp = NULL;
|
|
CString str;
|
|
DWORD err = ::W3GetAdminInformation((LPTSTR)lpszServer, &lp);
|
|
if (err != ERROR_SUCCESS)
|
|
{
|
|
TRACEEOLID("Failed to determine if SSL is installed");
|
|
|
|
return err;
|
|
}
|
|
|
|
fInstalled = (lp->dwEncCaps & ENC_CAPS_NOT_INSTALLED) == 0;
|
|
fEnabled = (lp->dwEncCaps & ENC_CAPS_DISABLED) == 0;
|
|
|
|
NETAPIBUFFERFREE(lp);
|
|
|
|
*/
|
|
|
|
//
|
|
// Above doesn't work for Beta I -- hack to assume true.
|
|
//
|
|
fInstalled = fEnabled = TRUE;
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
IsCertInstalledOnServer(
|
|
IN LPCTSTR lpszServerName,
|
|
IN DWORD dwInstance
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Check to see if a certificate is installed on this virtual server.
|
|
This routine only checks that the cert metabase key was read in.
|
|
|
|
by boydm
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if a certificate are installed, FALSE otherwise
|
|
|
|
--*/
|
|
{
|
|
CError err;
|
|
BOOL fCertInstalled = FALSE;
|
|
CW3InstanceProps * ppropInst;
|
|
|
|
//
|
|
// Get the instance properties
|
|
//
|
|
ppropInst = new CW3InstanceProps(lpszServerName, dwInstance);
|
|
|
|
//
|
|
// If it succeeded, load the data, then check the answer
|
|
//
|
|
if (ppropInst)
|
|
{
|
|
err = ppropInst->LoadData();
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
//
|
|
// Get the specific data to a local holder
|
|
// weird. You have to declare and assign the blob
|
|
// on different lines. Otherwise it gets constructed
|
|
// wrong and it tries to free an invalid
|
|
// memory block and bad things happen.
|
|
//
|
|
CBlob blobHash;
|
|
blobHash = ppropInst->m_CertHash;
|
|
|
|
// CString strStore = ppropInst->m_strCertStoreName;
|
|
|
|
//
|
|
// If the certificate hash is there,
|
|
// then we have a certificate
|
|
//
|
|
if (!blobHash.IsEmpty())
|
|
{
|
|
fCertInstalled = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clean up since we don't really need the ppropInst after this.
|
|
//
|
|
if (ppropInst)
|
|
{
|
|
delete ppropInst;
|
|
ppropInst = NULL;
|
|
}
|
|
|
|
//
|
|
// If that test failed, we may be admining a downlevel IIS4 machine.
|
|
// Unfortunately we can't tell by examining the capability bits,
|
|
// so look to see if the old certs are there.
|
|
//
|
|
if (!fCertInstalled)
|
|
{
|
|
CString strKey;
|
|
CMetaEnumerator me(lpszServerName, g_cszSvc);
|
|
HRESULT err = me.Next(strKey, g_cszSSLKeys);
|
|
fCertInstalled = SUCCEEDED(err);
|
|
}
|
|
|
|
return fCertInstalled;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
RunKeyManager(
|
|
IN LPCTSTR lpszServer OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper function to run the key manager application.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Notes:
|
|
|
|
Key manager is run synchronously.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Want to start key manager. I'm assuming
|
|
// here that the keyring app will be in the
|
|
// same directory as w3scfg.dll (safe assumption
|
|
// for the near future at least)
|
|
//
|
|
// CODEWORK: Move this to a registry key, so
|
|
// it can be changed later.
|
|
//
|
|
CString strPath;
|
|
CError err;
|
|
|
|
if (::GetModuleFileName(hInstance, strPath.GetBuffer(MAX_PATH), MAX_PATH))
|
|
{
|
|
int nLen = strPath.ReverseFind(_T('\\'));
|
|
|
|
if (nLen == -1)
|
|
{
|
|
TRACEEOLID("Bad module path");
|
|
err = ERROR_PATH_NOT_FOUND;
|
|
}
|
|
else
|
|
{
|
|
strPath.ReleaseBuffer(nLen);
|
|
strPath += _T("\\keyring.exe");
|
|
|
|
TRACEEOLID("Spawning " << strPath);
|
|
|
|
CString strParm;
|
|
|
|
if (lpszServer != NULL)
|
|
{
|
|
strParm.Format(_T("/remote:%s"), lpszServer);
|
|
}
|
|
|
|
TRACEEOLID(strParm);
|
|
TRACEEOLID(strPath);
|
|
|
|
if (_tspawnl(_P_WAIT, strPath, strPath, strParm, NULL) != 0)
|
|
{
|
|
err.GetLastWinError();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
err.GetLastWinError();
|
|
}
|
|
|
|
err.MessageBoxOnFailure();
|
|
}
|
|
|
|
|
|
|
|
void
|
|
InitializeDLL()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Perform additional initialisation as necessary
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
*/
|
|
{
|
|
#ifdef _DEBUG
|
|
|
|
afxMemDF |= checkAlwaysMemDF;
|
|
|
|
#endif // _DEBUG
|
|
|
|
#ifdef UNICODE
|
|
|
|
TRACEEOLID("Loading UNICODE w3scfg.dll");
|
|
|
|
#else
|
|
|
|
TRACEEOLID("Loading ANSI w3scfg.dll");
|
|
|
|
#endif UNICODE
|
|
|
|
::AfxEnableControlContainer();
|
|
|
|
#ifndef _COMSTATIC
|
|
//
|
|
// Initialize IISUI extension DLL
|
|
//
|
|
InitIISUIDll();
|
|
|
|
#endif // _COMSTATIC
|
|
|
|
}
|
|
|
|
|
|
|
|
CConfigDll NEAR theApp;
|
|
|
|
|
|
//
|
|
// 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()
|
|
|
|
|
|
|
|
BOOL
|
|
CConfigDll::InitInstance()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the instance
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE for success, FALSE for failure
|
|
|
|
--*/
|
|
{
|
|
BOOL bInit = CWinApp::InitInstance();
|
|
|
|
hInstance = ::AfxGetInstanceHandle();
|
|
ASSERT(hInstance);
|
|
|
|
InitializeDLL();
|
|
|
|
try
|
|
{
|
|
//
|
|
// Get the help path
|
|
//
|
|
ASSERT(m_pszHelpFilePath != NULL);
|
|
m_lpOldHelpPath = m_pszHelpFilePath;
|
|
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:
|
|
|
|
Exit instance handler
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
0 for success, or an error return code
|
|
|
|
--*/
|
|
{
|
|
m_pszHelpFilePath = m_lpOldHelpPath;
|
|
|
|
return CWinApp::ExitInstance();
|
|
}
|
|
|
|
|
|
|
|
CConfigDll::CConfigDll(
|
|
IN LPCTSTR pszAppName OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DLL CWinApp constructor
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: CWinApp(pszAppName)
|
|
{
|
|
}
|