windows-nt/Source/XPSP1/NT/inetsrv/iis/ui/admin/pwsext/eddir.cpp

675 lines
17 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
// this is the internal content - specific stuff related to the
// CShellExt object
#include "priv.h"
#include <tchar.h>
#include <iiscnfgp.h>
//
#include <inetinfo.h>
#include <winsvc.h>
#include <iwamreg.h>
#include <shlwapi.h>
#include "wrapmb.h"
#include "Sink.h"
#include "eddir.h"
#include "shellext.h"
#include "wrapmb.h"
//the key type string for the virtual directories
#define MDSZ_W3_VDIR_TYPE _T("IIsWebVirtualDir")
extern HINSTANCE g_hmodThisDll;
//Handle to this DLL itself.
BOOL MakeWAMApplication (IN LPCTSTR pszPath, IN BOOL fCreate);
BOOL MyFormatString1 (IN LPTSTR pszSource, IN DWORD cchMax, LPTSTR pszReplace);
//---------------------------------------------------------------
INT_PTR CALLBACK
EditDirDlgProc (HWND hDlg,
UINT uMessage,
WPARAM wParam,
LPARAM lParam)
{
//the pointer to the object is passed in as the private lParam, store it away
if (uMessage == WM_INITDIALOG)
{
SetWindowLongPtr (hDlg, DWLP_USER, lParam);
}
//dialog object pointer from the window
CEditDirectory * pdlg = (CEditDirectory *) GetWindowLongPtr (hDlg, DWLP_USER);
if (!pdlg)
return FALSE;
//let the object do the work
return pdlg->OnMessage (hDlg, uMessage, wParam, lParam);
}
//=====================================================================================
//---------------------------------------------------------------
CEditDirectory::CEditDirectory (HWND hParent):
m_hParent (hParent),
m_bool_read (FALSE),
m_bool_write (FALSE),
m_bool_dirbrowse (FALSE),
m_bool_source (FALSE),
m_bool_oldSource (FALSE),
m_int_AppPerms (APPPERM_NONE),
// m_pMBCom (NULL),
m_fNewItem (FALSE),
m_hDlg (NULL)
{
}
//---------------------------------------------------------------
CEditDirectory::~CEditDirectory ()
{
}
//---------------------------------------------------------------
INT_PTR CEditDirectory::DoModal ()
{
return DialogBoxParam (
g_hmodThisDll, //handle to application instance
MAKEINTRESOURCE (IDD_ALIAS), //identifies dialog box template
m_hParent, //handle to owner window
EditDirDlgProc, //pointer to dialog box procedure
(LPARAM) this // initialization value
);
}
//---------------------------------------------------------------
//return FALSE if we do NOT handle the message
BOOL CEditDirectory::OnMessage (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
//return success
return OnInitDialog (hDlg);
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDC_FULLCONTROL:
OnSource (hDlg);
return TRUE;
case IDC_READ:
OnRead (hDlg);
return TRUE;
case IDC_WRITE:
OnWrite (hDlg);
return TRUE;
case IDOK:
OnOK (hDlg);
return TRUE;
case IDCANCEL:
EndDialog (IDCANCEL);
return TRUE;
}
break;
};
//return whether or not we handled the message
return FALSE;
}
//----------------------------------------------------------------
//CDialog simulation routines
void CEditDirectory::UpdateData (BOOL fDialogToData)
{
//get the data from the dialog
if (fDialogToData)
{
//get the text items first
GetWindowText (m_hEditAlias, m_sz_alias, MAX_PATH);
GetWindowText (m_hEditPath, m_sz_path, MAX_PATH);
//read the checkboxes
m_bool_read = (SendMessage (m_hChkRead, BM_GETCHECK, 0, 0) == BST_CHECKED);
m_bool_write = (SendMessage (m_hChkWrite, BM_GETCHECK, 0, 0) == BST_CHECKED);
m_bool_dirbrowse = (SendMessage (m_hChkDirBrowse, BM_GETCHECK, 0, 0) == BST_CHECKED);
m_bool_source = (SendMessage (m_hChkSource, BM_GETCHECK, 0, 0) == BST_CHECKED);
//read the AppPerm radio buttons
if (SendMessage (m_hRdoScripts, BM_GETCHECK, 0, 0) == BST_CHECKED)
{
m_int_AppPerms = APPPERM_SCRIPTS;
}
else if (SendMessage (m_hRdoExecute, BM_GETCHECK, 0, 0) == BST_CHECKED)
{
m_int_AppPerms = APPPERM_EXECUTE;
}
else
{
m_int_AppPerms = APPPERM_NONE;
}
}
else
{
//put it back into the dialog
// set the text items first
SetWindowText (m_hEditAlias, m_sz_alias);
SetWindowText (m_hEditPath, m_sz_path);
//set the checkboxes
SendMessage (m_hChkRead, BM_SETCHECK, m_bool_read ? BST_CHECKED :
BST_UNCHECKED, 0);
SendMessage (m_hChkWrite, BM_SETCHECK, m_bool_write ? BST_CHECKED :
BST_UNCHECKED, 0);
SendMessage (m_hChkDirBrowse, BM_SETCHECK, m_bool_dirbrowse ?
BST_CHECKED : BST_UNCHECKED, 0);
SendMessage (m_hChkSource, BM_SETCHECK, m_bool_source ? BST_CHECKED
: BST_UNCHECKED, 0);
//set the AppPerm radio buttons
SendMessage (m_hRdoNone, BM_SETCHECK,
(m_int_AppPerms == APPPERM_NONE) ? BST_CHECKED : BST_UNCHECKED, 0);
SendMessage (m_hRdoScripts, BM_SETCHECK,
(m_int_AppPerms == APPPERM_SCRIPTS) ? BST_CHECKED : BST_UNCHECKED, 0);
SendMessage (m_hRdoExecute, BM_SETCHECK,
(m_int_AppPerms == APPPERM_EXECUTE) ? BST_CHECKED : BST_UNCHECKED, 0);
}
}
//----------------------------------------------------------------
BOOL CEditDirectory::InitHandles (HWND hDlg)
{
m_hDlg = hDlg;
m_hEditAlias = GetDlgItem (hDlg, IDC_ALIAS);
m_hEditPath = GetDlgItem (hDlg, IDC_PATH);
m_hChkRead = GetDlgItem (hDlg, IDC_READ);
m_hChkWrite = GetDlgItem (hDlg, IDC_WRITE);
m_hChkDirBrowse = GetDlgItem (hDlg, IDC_DIRBROWSE);
m_hChkSource = GetDlgItem (hDlg, IDC_FULLCONTROL);
m_hRdoNone = GetDlgItem (hDlg, IDC_RDO_NONE);
m_hRdoExecute = GetDlgItem (hDlg, IDC_RDO_EXECUTE);
m_hRdoScripts = GetDlgItem (hDlg, IDC_RDO_SCRIPTS);
return TRUE;
}
//----------------------------------------------------------------
BOOL CEditDirectory::OnInitDialog (HWND hDlg)
{
BOOL f = FALSE;
CWrapMetaBase mb;
DWORD dword;
TCHAR sz[MAX_PATH];
InitHandles (hDlg);
ZeroMemory (sz, MAX_PATH);
//keep a copy of the original alias for later verification
StrCpy (m_szOrigAlias,
*m_sz_alias == _T ('/') ? m_sz_alias + 1 : m_sz_alias);
StrCpy (m_sz_alias, m_szOrigAlias);
//open up the metabase and read in the initial values
// first things first.init the mb object
if (!mb.FInit (m_pMBCom))
{
goto cleanup;
}
//build the metapath
StrCpy (sz, m_szRoot);
StrCat (sz, _T ("/"));
StrCat (sz, m_sz_alias);
//open the object - use root defaults if this is a new item
if (m_fNewItem || !mb.Open (sz))
{
//if the node doesn 't exist - get the default values of the root
if (!mb.Open (m_szRoot))
{
//if that doesn 't work - fail
goto cleanup;
}
}
//read the flags
if (mb.GetDword (_T (""), MD_ACCESS_PERM, IIS_MD_UT_FILE, &dword, METADATA_INHERIT))
{
//interpret that thing
m_bool_read = (dword & MD_ACCESS_READ) > 0;
m_bool_write = (dword & MD_ACCESS_WRITE) > 0;
m_bool_source = (dword & MD_ACCESS_SOURCE) > 0;
//choose the correct app permissions radio button
m_int_AppPerms = APPPERM_NONE;
if (dword & MD_ACCESS_EXECUTE)
{
m_int_AppPerms = APPPERM_EXECUTE;
}
else if (dword & MD_ACCESS_SCRIPT)
{
m_int_AppPerms = APPPERM_SCRIPTS;
}
}
//the dir browsing flag is stored in a different field
if (mb.GetDword (_T (""), MD_DIRECTORY_BROWSING, IIS_MD_UT_FILE, &dword, METADATA_INHERIT))
{
m_bool_dirbrowse = (dword & MD_DIRBROW_ENABLED) > 0;
}
//close the metabase
mb.Close ();
//if this is a new item, force the app perms to scripts
if (m_fNewItem)
{
m_int_AppPerms = APPPERM_SCRIPTS;
}
//set the data into place
UpdateData (FALSE);
//prep the source control button
m_bool_oldSource = m_bool_source;
EnableSourceControl ();
cleanup:
return f;
}
//----------------------------------------------------------------
//we need to make sure that there is something in the alias field
// an empty alias is not OK
void CEditDirectory::OnOK (HWND hDlg)
{
BOOL f;
DWORD err;
DWORD dword;
int iPar;
CWrapMetaBase mb;
TCHAR szPath[MAX_PATH];
TCHAR szParent[MAX_PATH];
TCHAR sz[MAX_PATH];
TCHAR szCaption[MAX_PATH];
ZeroMemory (sz, MAX_PATH);
ZeroMemory (szPath, MAX_PATH);
ZeroMemory (szParent, MAX_PATH);
ZeroMemory (szCaption, MAX_PATH);
UpdateData (TRUE);
//trim leading and trailing spaces
TrimLeft (m_sz_alias);
TrimRight (m_sz_alias);
//first test is to see if there is anything in it
if (*m_sz_alias == 0)
{
LoadString (g_hmodThisDll, IDS_PAGE_TITLE, szCaption, MAX_PATH);
LoadString (g_hmodThisDll, IDS_EMPTY_ALIAS, sz, MAX_PATH);
MessageBox (hDlg, sz, szCaption, MB_OK);
goto cleanup;
}
//at this point we need to check if write and execute / script are set as this
// could open a potential security hole.If they are set, then alert the user
// and ask if they reall really want to do that
if ( m_bool_write
&& ((m_int_AppPerms == APPPERM_SCRIPTS) || (m_int_AppPerms == APPPERM_EXECUTE))
)
{
LoadString (g_hmodThisDll, IDS_WRITEEXECUTE_WARNING, sz, MAX_PATH);
LoadString (g_hmodThisDll, IDS_WARNING, szCaption, MAX_PATH);
if (MessageBox (hDlg, sz, szCaption, MB_YESNO |
MB_ICONEXCLAMATION) != IDYES)
goto cleanup;
}
//get ready
if (!mb.FInit (m_pMBCom))
goto cleanup;
//next, if a parent has been specified, it must exist
// the alias may not contain a '/' character
if (NULL != StrPBrk (m_sz_alias, _T ("\\/")))
{
LPTSTR pPar = StrRChr (m_sz_alias, NULL, _T ('/'));
if (NULL == pPar)
pPar = StrRChr (m_sz_alias, NULL, _T ('\\'));
//make the parental path
StrCpy (szParent, m_szRoot);
StrCat (szParent, _T ("/"));
StrCatN (szParent, m_sz_alias, m_sz_alias - pPar);
//make sure the parent is there
if (!mb.Open (szParent))
{
LoadString (g_hmodThisDll, IDS_PAGE_TITLE, szCaption, MAX_PATH);
LoadString (g_hmodThisDll, IDS_NO_PARENT, sz, MAX_PATH);
MessageBox (hDlg, sz, szCaption, MB_OK);
goto cleanup;
}
//close right away - we are ok
mb.Close ();
}
//Now we need to make sure that alias isn 't already taken
_tcscpy (szPath, m_szRoot);
_tcscat (szPath, _T ("/"));
_tcscat (szPath, m_sz_alias);
//try to open the object
// however, if it is not a new object, and the alias has not changed,
// do not see if the object is there becuase we know that it is and it is ok in this case
if (_tcsicmp (m_sz_alias, m_szOrigAlias) || m_fNewItem)
{
if (mb.Open (szPath))
{
//we did open it ! Close it right away
mb.Close ();
//tell the user to pick another name
LoadString (g_hmodThisDll, IDS_ALIAS_IS_TAKEN, sz, MAX_PATH);
LoadString (g_hmodThisDll, IDS_PAGE_TITLE, szCaption, MAX_PATH);
MyFormatString1 (sz, MAX_PATH, m_sz_alias);
MessageBox (hDlg, sz, szCaption, MB_OK);
goto cleanup;
}
}
SetCursor (LoadCursor (NULL, IDC_WAIT));
//if the name has changed, delete the old one
if (_tcscmp (m_szOrigAlias, m_sz_alias) && !m_fNewItem)
{
//first we have to open the root
if (mb.Open (m_szRoot, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE))
{
MakeWAMApplication (m_szOrigAlias, FALSE);
f = mb.DeleteObject (m_szOrigAlias);
mb.Close ();
}
}
//if we are creating a new object - then do so
if (_tcscmp (m_szOrigAlias, m_sz_alias) || m_fNewItem)
{
//first we have to open the root
if (mb.Open (m_szRoot, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE))
{
f = mb.AddObject (m_sz_alias);
//set the key type
f = mb.SetString (m_sz_alias, MD_KEY_TYPE, IIS_MD_UT_SERVER,
MDSZ_W3_VDIR_TYPE, 0);
mb.Close ();
//create the WAM application at the new virtual directory location
MakeWAMApplication (szPath, TRUE);
}
else
err = GetLastError ();
}
//make sure we have the right path again
_tcscpy (szPath, m_szRoot);
_tcscat (szPath, _T ("/"));
_tcscat (szPath, m_sz_alias);
//open the target new item and write out its parameters
if (mb.Open (szPath, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE))
{
//set the path into place
f = mb.SetString (_T (""), MD_VR_PATH, IIS_MD_UT_FILE, m_sz_path);
//put the access flags into place.There are other flags than the ones that are manupulated
// here, so be careful to read the value first, then flip the flags, then write it back
dword = 0;
mb.GetDword (_T (""), MD_ACCESS_PERM, IIS_MD_UT_FILE, &dword, METADATA_INHERIT);
//read permissions
if (m_bool_read)
dword |= MD_ACCESS_READ;
else
dword &= ~MD_ACCESS_READ;
// write permissions
if (m_bool_write)
dword |= MD_ACCESS_WRITE;
else
dword &= ~MD_ACCESS_WRITE;
// source read permissions
if (m_bool_source)
dword |= MD_ACCESS_SOURCE;
else
dword &= ~MD_ACCESS_SOURCE;
// since the app permissions are now a set of radio buttons, use a case to discern
switch (m_int_AppPerms)
{
case APPPERM_NONE:
dword &= ~MD_ACCESS_SCRIPT;
dword &= ~MD_ACCESS_EXECUTE;
break;
case APPPERM_SCRIPTS:
dword |= MD_ACCESS_SCRIPT;
dword &= ~MD_ACCESS_EXECUTE;
break;
case APPPERM_EXECUTE:
dword |= MD_ACCESS_SCRIPT;
dword |= MD_ACCESS_EXECUTE;
break;
};
//write the dword back into the metabase
f = mb.SetDword (_T (""), MD_ACCESS_PERM, IIS_MD_UT_FILE, dword);
//------------------
//the dir browsing flag is stored in a different field - so do it again
dword = 0;
mb.GetDword (_T (""), MD_DIRECTORY_BROWSING, IIS_MD_UT_FILE, &dword, METADATA_INHERIT);
//script permissions
if (m_bool_dirbrowse)
dword |= MD_DIRBROW_ENABLED;
else
dword &= ~MD_DIRBROW_ENABLED;
// write the dword back into the metabase
f = mb.SetDword (_T (""), MD_DIRECTORY_BROWSING, IIS_MD_UT_FILE, dword);
//finish up
mb.Close ();
}
//make sure the string goes back
UpdateData (FALSE);
// do the default...
EndDialog (IDOK);
//cleanup the strings
cleanup:
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
//----------------------------------------------------------------
void CEditDirectory::EnableSourceControl ()
{
//get the currect button values
UpdateData (TRUE);
//if both read and write are unchecked, then we clear and disable source control
if (!m_bool_read && !m_bool_write)
{
//save the value of source control
m_bool_oldSource = m_bool_source;
//clear the source control
m_bool_source = FALSE;
UpdateData (FALSE);
//disable the source control window
EnableWindow (m_hChkSource, FALSE);
}
else
{
//we enable source control
// disable the source control window
EnableWindow (m_hChkSource, TRUE);
//and set the value back
m_bool_source = m_bool_oldSource;
UpdateData (FALSE);
}
}
//----------------------------------------------------------------
void CEditDirectory::OnRead (HWND hDlg)
{
EnableSourceControl ();
}
//----------------------------------------------------------------
void CEditDirectory::OnWrite (HWND hDlg)
{
EnableSourceControl ();
}
//----------------------------------------------------------------
void CEditDirectory::OnSource (HWND hDlg)
{
UpdateData (TRUE);
m_bool_oldSource = m_bool_source;
}
//----------------------------------------------------------------
//return an index to the position of first ch in pszSearch in the string
// or return -1 if none are there
int CEditDirectory::FindOneOf (LPTSTR psz, LPCTSTR pszSearch)
{
PTCHAR p = _tcspbrk (psz, pszSearch);
if (!p)
return -1;
return (int) (p - psz);
}
//----------------------------------------------------------------
//return an index to the position of ch in the string
// or return -1 if it is not there
int CEditDirectory::FindLastChr (LPTSTR psz, TCHAR ch)
{
PTCHAR p = _tcsrchr (psz, ch);
if (!p)
return -1;
return (int) (p - psz);
}
//----------------------------------------------------------------
//trim leading whitespace
void CEditDirectory::TrimLeft (LPTSTR psz)
{
TCHAR buf[8];
ZeroMemory (&buf, sizeof (buf));
//copy over the first character
_tcsncpy (buf, psz, 1);
//and compare
while (_tcscmp (buf, _T (" ")) == 0)
{
_tcscpy (psz, _tcsinc (psz));
_tcsncpy (buf, psz, 1);
}
}
//----------------------------------------------------------------
//trim trailing whitespace
void CEditDirectory::TrimRight (LPTSTR psz)
{
TCHAR buf[8];
DWORD len;
ZeroMemory (&buf, sizeof (buf));
//copy over the last character
len = _tcslen (psz);
_tcsncpy (buf, _tcsninc (psz, len - 1), 1);
//and compare
while (_tcscmp (buf, _T (" ")) == 0)
{
//truncate the string
*(_tcsninc (psz, len - 1)) = 0;
//start over
len = _tcslen (psz);
_tcsncpy (buf, _tcsninc (psz, len - 1), 1);
}
}
#if 0
//----------------------------------------------------------------
//trim trailing whitespace
void CEditDirectory::TrimRight (LPTSTR psz)
{
TCHAR buf[8];
DWORD len;
ZeroMemory (&buf, sizeof (buf));
//copy over the last character
len = _tcslen (psz);
_tcsncpy (buf, _tcsninc (psz, len - 1), 1);
//and compare
while (_tcscmp (buf, _T (" ")) == 0)
{
//truncate the string
*(_tcsninc (psz, len - 1)) = 0;
//start over
len = _tcslen (psz);
_tcsncpy (buf, _tcsninc (psz, len - 1), 1);
}
}
#endif