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

486 lines
15 KiB
C++

// AppMapPg.cpp : implementation file
//
#include "stdafx.h"
#include <iadmw.h>
#include "cnfgprts.h"
#include "ListRow.h"
#include "AppMapPg.h"
#include "AppEdMpD.h"
#include "wrapmb.h"
#include "metatool.h"
#include <iiscnfg.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
enum {
COL_EXTENSION = 0,
COL_PATH,
COL_EXCLUSIONS
};
#define SZ_ROOT _T("/lm/w3svc")
/////////////////////////////////////////////////////////////////////////////
// CAppMapPage property page
IMPLEMENT_DYNCREATE(CAppMapPage, CPropertyPage)
//----------------------------------------------------------------
CAppMapPage::CAppMapPage() : CPropertyPage(CAppMapPage::IDD),
m_fInitialized( FALSE ),
m_fLocalMachine( FALSE )
{
//{{AFX_DATA_INIT(CAppMapPage)
m_bool_cache_isapi = FALSE;
//}}AFX_DATA_INIT
}
//----------------------------------------------------------------
CAppMapPage::~CAppMapPage()
{
}
//----------------------------------------------------------------
void CAppMapPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAppMapPage)
DDX_Control(pDX, IDC_CHK_CACHE_ISAPI, m_btn_cache_isapi);
DDX_Check(pDX, IDC_CHK_CACHE_ISAPI, m_bool_cache_isapi);
DDX_Control(pDX, IDC_REMOVE, m_btn_remove);
DDX_Control(pDX, IDC_EDIT, m_btn_edit);
DDX_Control(pDX, IDC_LIST, m_clist_list);
//}}AFX_DATA_MAP
}
//----------------------------------------------------------------
BEGIN_MESSAGE_MAP(CAppMapPage, CPropertyPage)
//{{AFX_MSG_MAP(CAppMapPage)
ON_BN_CLICKED(IDC_CHK_CACHE_ISAPI, OnChkCacheIsapi)
ON_BN_CLICKED(IDC_ADD, OnAdd)
ON_BN_CLICKED(IDC_EDIT, OnEdit)
ON_BN_CLICKED(IDC_REMOVE, OnRemove)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST, OnItemchangedList)
ON_NOTIFY(NM_DBLCLK, IDC_LIST, OnDblclkList)
//}}AFX_MSG_MAP
ON_COMMAND(ID_HELP_FINDER, DoHelp)
ON_COMMAND(ID_HELP, DoHelp)
ON_COMMAND(ID_CONTEXT_HELP, DoHelp)
ON_COMMAND(ID_DEFAULT_HELP, DoHelp)
END_MESSAGE_MAP()
//---------------------------------------------------------------------------
void CAppMapPage::DoHelp()
{
WinHelp( HIDD_APPMAPS_MAPS );
}
//----------------------------------------------------------------
void CAppMapPage::Init()
{
CString sz;
DWORD dw = 0;
WCHAR* pData = NULL;
CString szMap;
CString szSection;
int i = 0;
UpdateData( TRUE );
//
// RONALDM: The word "ALL" is displayed for empty verb lists,
// though it should not be written to the metabase.
//
VERIFY(m_szAll.LoadString(IDS_VERBS_ALL));
// prepare the list for use
sz.LoadString( IDS_APP_EXTENSION );
i = m_clist_list.InsertColumn( COL_EXTENSION, sz, LVCFMT_LEFT, 58 );
sz.LoadString( IDS_APP_EXE_PATH );
i = m_clist_list.InsertColumn( COL_PATH, sz, LVCFMT_LEFT, 204 );
sz.LoadString( IDS_APP_EXCLUSIONS );
i = m_clist_list.InsertColumn( COL_EXCLUSIONS, sz, LVCFMT_LEFT, 72 );
// we will just be pulling stuff out of the metabase here
// prepare the metabase wrapper
CWrapMetaBase mbWrap;
if ( !mbWrap.FInit(m_pMB) ) return;
// arg arg arg. For things like directories, the metapath may not exist
// seperate the partial path from the base - the root is always SZ_ROOT
sz = SZ_ROOT;
m_szPartial = m_szMeta.Right(m_szMeta.GetLength() - sz.GetLength() );
// open the target
if ( mbWrap.Open( SZ_ROOT, METADATA_PERMISSION_READ ) )
{
// read the session timeout information
if ( mbWrap.GetDword( m_szPartial, MD_CACHE_EXTENSIONS, IIS_MD_UT_FILE, &dw, METADATA_INHERIT | METADATA_PARTIAL_PATH ) )
m_bool_cache_isapi = (BOOL)dw;
else
m_bool_cache_isapi = FALSE; // default
// get the big script map string
dw = 0;
pData = (WCHAR*)mbWrap.GetData( m_szPartial, MD_SCRIPT_MAPS, IIS_MD_UT_FILE, MULTISZ_METADATA, &dw, METADATA_INHERIT | METADATA_PARTIAL_PATH );
// close the metabase
mbWrap.Close();
}
// set the data into place
UpdateData( FALSE );
// if we got the mappings string, parse it now - no need to keep the metabase open
if ( pData )
{
WCHAR* pstr = (WCHAR*)pData;
// loop through the sub-strings in the multi-sz
i = -1;
while( pstr[0] )
{
// get the sub-string
szMap = pstr;
// Get the sub-sections of the sub-string
szSection = szMap.Left( szMap.Find(',') );
szMap = szMap.Right( szMap.GetLength() - szSection.GetLength() - 1 );
// add the extension to the list
i = m_clist_list.InsertItem( i+1, szSection );
// Get the sub-sections of the sub-string
szSection = szMap.Left( szMap.Find(',') );
szMap = szMap.Right( szMap.GetLength() - szSection.GetLength() - 1 );
// add the path to the list
m_clist_list.SetItemText( i, COL_PATH, szSection );
// Get the sub-sections of the sub-string
if ( szMap.Find(',') >= 0 )
szSection = szMap.Left( szMap.Find(',') );
else
szSection = szMap;
szMap = szMap.Right( szMap.GetLength() - szSection.GetLength() - 1 );
// convert the flags string into a ddword
swscanf( (PTCHAR)(LPCTSTR)szSection, _T("%d"), &dw );
// save the dword on the list item
m_clist_list.SetItemData( i, dw );
// the remainder of the list is the list of ISAPI method exclusions
// add the exclusions to the list
//
// RONALDM Change, Bug 178423: If no exclusions (and they're
// now inclusions, rather than exclusions) are present, the word
// "ALL" should be placed in the exclusions column.
//
m_clist_list.SetItemText(i, COL_EXCLUSIONS, (szMap.IsEmpty() ? m_szAll : szMap));
// advance the pstr
pstr += wcslen(pstr) + 1;
}
// now we can release the buffer
mbWrap.FreeWrapData( pData );
}
// according to bug #152234 the cache ISAPI extensions should only be exposed on the
// master properties or the virtual server level. So - we need to detect if we are on
// this level and if we are NOT, then disable the control
//
// The easiest way to determin if we are deeper than the virtual server is to count
// the slash characters. If there are more than 3, then we are at a virt dir or phys dir
DWORD nLevels = 0;
int iSlash;
CString szPath = m_szMeta;
while ( (iSlash = szPath.Find( _T('/') )) >= 0 )
{
nLevels++;
szPath = szPath.Right( szPath.GetLength() - (iSlash + 1) );
}
// if the number of levels is greater than 3 then it is a virt dir. Disable the isapi cache option
if ( nLevels > 3 )
m_btn_cache_isapi.EnableWindow( FALSE );
}
//---------------------------------------------------------------------------
void CAppMapPage::EnableItems()
{
UpdateData( TRUE );
if ( m_clist_list.GetSelectedCount() == 1 )
{
m_btn_edit.EnableWindow( TRUE );
m_btn_remove.EnableWindow( TRUE );
}
else
{
m_btn_edit.EnableWindow( FALSE );
m_btn_remove.EnableWindow( FALSE );
}
}
//----------------------------------------------------------------
// blow away the parameters
void CAppMapPage::BlowAwayParameters()
{
// prepare the metabase wrapper
CWrapMetaBase mbWrap;
if ( !mbWrap.FInit(m_pMB) ) return;
// open the target
if ( mbWrap.Open( m_szMeta, METADATA_PERMISSION_WRITE ) )
{
mbWrap.DeleteData( _T(""), MD_CACHE_EXTENSIONS, DWORD_METADATA );
mbWrap.DeleteData( _T(""), MD_SCRIPT_MAPS, DWORD_METADATA );
// mbWrap.DeleteData( _T(""), MD_CACHE_EXTENSIONS, IIS_MD_UT_FILE, DWORD_METADATA );
// mbWrap.DeleteData( _T(""), MD_SCRIPT_MAPS, IIS_MD_UT_FILE, DWORD_METADATA );
// close the metabase
mbWrap.Close();
}
}
/////////////////////////////////////////////////////////////////////////////
// CAppMapPage message handlers
//----------------------------------------------------------------
BOOL CAppMapPage::OnApply()
{
LPTSTR lpszBuffer;
DWORD dwSize;
DWORD i;
BOOL f;
CString szExclude;
CString szNewMap;
CString szExtension;
CString szPath;
DWORD dw;
UpdateData( TRUE );
// build the multisz string. Use the * character as a seperator for now, then replace it with nulls
CString szMappings;
// build the string
DWORD nItems = m_clist_list.GetItemCount();
for ( i = 0; i < nItems; i++ )
{
// prep the optional ISAPI exclution string
szExclude = m_clist_list.GetItemText(i, COL_EXCLUSIONS);
//----------------------------------------------------------------------------------------
//
// RONALDM: The word "ALL" is a visual indicator that should be replaced
// with an empty exclusion list.
//
szExclude.TrimLeft();
szExclude.TrimRight();
if (szExclude.CompareNoCase(m_szAll) == 0)
{
szExclude.Empty();
}
//----------------------------------------------------------------------------------------
if ( !szExclude.IsEmpty() )
szExclude = _T(',') + szExclude;
szNewMap;
szExtension = m_clist_list.GetItemText(i, COL_EXTENSION);
szPath = m_clist_list.GetItemText(i, COL_PATH);
// IA64 - OK to cast to DWORD as it is a small numerical flag
dw = (DWORD)m_clist_list.GetItemData(i);
szNewMap.Format( _T("%s,%s,%d%s\n"), szExtension, szPath, dw, szExclude );
szMappings += szNewMap;
}
// put on the last delimiter
szMappings += _T('\n');
// record the length
dwSize = szMappings.GetLength();
// transform it into a multisz
lpszBuffer = szMappings.GetBuffer(MAX_PATH+1);
while( lpszBuffer[i] )
{
if ( lpszBuffer[i] == _T('\n') )
lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
i++;
}
// prepare the metabase wrapper
CWrapMetaBase mbWrap;
if ( !mbWrap.FInit(m_pMB) ) return FALSE;
// script file size
f = SetMetaDword(m_pMB, m_szServer, m_szMeta, _T(""), MD_CACHE_EXTENSIONS, IIS_MD_UT_FILE,
m_bool_cache_isapi, TRUE);
// script mappings
f = SetMetaMultiSz(m_pMB, m_szServer, m_szMeta, _T(""), MD_SCRIPT_MAPS, IIS_MD_UT_FILE,
lpszBuffer, dwSize, TRUE );
// close the metabase
mbWrap.Close();
// clean up
szMappings.ReleaseBuffer(-1);
SetModified( FALSE );
return CPropertyPage::OnApply();
}
//----------------------------------------------------------------
BOOL CAppMapPage::OnSetActive()
{
if ( !m_fInitialized )
{
Init();
m_fInitialized = TRUE;
}
return CPropertyPage::OnSetActive();
}
//----------------------------------------------------------------
void CAppMapPage::OnChkCacheIsapi()
{
SetModified();
}
//----------------------------------------------------------------
void CAppMapPage::OnAdd()
{
// set up a default edit box
CAppEditMapDlg dlg;
dlg.m_pList = &m_clist_list;
dlg.m_fNewMapping = TRUE;
dlg.m_fLocalMachine = m_fLocalMachine;
dlg.m_dwFlags = MD_SCRIPTMAPFLAG_SCRIPT;
// ask the user to edit the mapping
if ( dlg.DoModal() == IDOK )
{
// we want to add the extension to the end of the list. So get the number that
// are already there.
DWORD numExtensions = m_clist_list.GetItemCount();
// add the extension to the list
DWORD i = m_clist_list.InsertItem( numExtensions, dlg.m_sz_extension );
// add the path to the list
m_clist_list.SetItemText( i, COL_PATH, dlg.m_sz_executable );
// save the dword on the list item
m_clist_list.SetItemData( i, dlg.m_dwFlags );
// set the exclusion list
m_clist_list.SetItemText(
i,
COL_EXCLUSIONS,
(dlg.m_sz_exclusions.IsEmpty() ? m_szAll : dlg.m_sz_exclusions)
);
SetModified();
}
}
//----------------------------------------------------------------
void CAppMapPage::OnEdit()
{
// make sure something is selcted
if ( m_clist_list.GetSelectedCount() != 1 )
return;
// get the index of the selected item
int iSel = m_clist_list.GetNextItem( -1, LVNI_SELECTED );
// set up a default edit box
CAppEditMapDlg dlg;
dlg.m_fLocalMachine = m_fLocalMachine;
dlg.m_fNewMapping = FALSE;
dlg.m_pList = &m_clist_list;
// IA64 - OK to cast as this is a numerical flag 1,2,3,4 etc...
dlg.m_dwFlags = (DWORD)m_clist_list.GetItemData( iSel );
dlg.m_sz_extension = m_clist_list.GetItemText( iSel, COL_EXTENSION );
dlg.m_sz_executable = m_clist_list.GetItemText( iSel, COL_PATH );
dlg.m_sz_exclusions = m_clist_list.GetItemText( iSel, COL_EXCLUSIONS );
//
// RONALDM: Handle "(all)" exclusions cleanly
//
if (dlg.m_sz_exclusions.CompareNoCase(m_szAll) == 0)
{
dlg.m_sz_exclusions.Empty();
}
// run the edit box
if ( dlg.DoModal() == IDOK )
{
// set the path to the list
m_clist_list.SetItemText( iSel, COL_EXTENSION, dlg.m_sz_extension );
// set the path to the list
m_clist_list.SetItemText( iSel, COL_PATH, dlg.m_sz_executable );
// set the dword on the list item
m_clist_list.SetItemData( iSel, dlg.m_dwFlags );
//
// set the exclusion list
//
// RONALDM: blank == "(all)"
//
m_clist_list.SetItemText(
iSel,
COL_EXCLUSIONS,
(dlg.m_sz_exclusions.IsEmpty() ? m_szAll : dlg.m_sz_exclusions)
);
SetModified();
}
}
//----------------------------------------------------------------
void CAppMapPage::OnRemove()
{
// make sure something is selcted
if ( m_clist_list.GetSelectedCount() != 1 )
return;
// ask the user if that is what they really want to do
if ( AfxMessageBox(IDS_APP_MAP_REMOVE_CONFIRM, MB_YESNO) != IDYES )
return;
// get the index of the selected item
int iSel = m_clist_list.GetNextItem( -1, LVNI_SELECTED );
// delete the item
m_clist_list.DeleteItem( iSel );
SetModified();
}
//----------------------------------------------------------------
void CAppMapPage::OnItemchangedList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
EnableItems();
*pResult = 0;
}
//----------------------------------------------------------------
void CAppMapPage::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult)
{
OnEdit();
*pResult = 0;
}