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

711 lines
15 KiB
C++

/*++
Copyright (c) 1994-1998 Microsoft Corporation
Module Name :
dirbrows.cpp
Abstract:
Directory Browser Dialog. Allow browsing for directories only.
optionally allows UNC conversions for remote paths.
Author:
Ronald Meijer (ronaldm)
Project:
Internet Services Manager
Revision History:
--*/
//
// Include Files
//
#include "stdafx.h"
#include "comprop.h"
#include "dirbrows.h"
#include <dlgs.h>
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
static
int
BrowseCallbackProc(
IN HWND hwnd,
IN UINT uMsg,
IN LPARAM lParam,
IN LPARAM lpData
)
/*++
Routine Description:
Callback function for the folder browser
Arguments:
hwnd : Handle to the browse dialog box. The callback function can
send the following messages to this window:
BFFM_ENABLEOK Enables the OK button if the wParam parameter
is nonzero or disables it if wParam is zero.
BFFM_SETSELECTION Selects the specified folder. The lParam
parameter is the PIDL of the folder to select
if wParam is FALSE, or it is the path of the
folder otherwise.
BFFM_SETSTATUSTEXT Sets the status text to the null-terminated
string specified by the lParam parameter.
uMsg : Value identifying the event. This parameter can be one of the
following values:
0 Initialize dir path. lParam is the path.
BFFM_INITIALIZED The browse dialog box has finished
initializing. lpData is NULL.
BFFM_SELCHANGED The selection has changed. lpData
is a pointer to the item identifier list for
the newly selected folder.
lParam : Message-specific value. For more information, see the
description of uMsg.
lpData : Application-defined value that was specified in the lParam
member of the BROWSEINFO structure.
Return Value:
0
--*/
{
static LPCTSTR lpstrDir = NULL;
switch(uMsg)
{
case 0:
lpstrDir = (LPCTSTR)lParam;
break;
case BFFM_INITIALIZED:
//
// Dialog initialized -- select desired folder
//
if (lpstrDir != NULL)
{
::SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpstrDir);
}
break;
}
return 0;
}
CDirBrowseDlg::CDirBrowseDlg(
IN CWnd * pParent OPTIONAL,
IN LPCTSTR lpszInitialDir OPTIONAL
)
/*++
Routine Description:
Constructor for directory browser dialog
Arguments:
CWnd * pParent : Parent window or NULL
LPCTSTR lpszInitialDir : Initial directory, or NULL for current directory
Return Value:
N/A
--*/
: m_strInitialDir(lpszInitialDir)
{
VERIFY(m_strTitle.LoadString(IDS_BROWSE_DIRECTORY));
m_bi.pidlRoot = NULL;
m_bi.hwndOwner = pParent ? pParent->m_hWnd : NULL;
m_bi.pszDisplayName = m_szBuffer;
m_bi.lpszTitle = m_strTitle;
m_bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS,
m_bi.lpfn = BrowseCallbackProc;
m_bi.lParam = 0;
//
// Let the callback function know the default dir is
//
lpszInitialDir = !m_strInitialDir.IsEmpty()
? (LPCTSTR)m_strInitialDir
: NULL;
BrowseCallbackProc(m_bi.hwndOwner, 0, (LPARAM)lpszInitialDir, NULL);
}
CDirBrowseDlg::~CDirBrowseDlg()
/*++
Routine Description:
Destructor for directory browser dialog
Arguments:
N/A
Return Value:
N/A
--*/
{
if (m_bi.pidlRoot != NULL)
{
LPITEMIDLIST pidl = (LPITEMIDLIST)m_bi.pidlRoot;
//
// Free using shell allocator
//
LPMALLOC pMalloc;
if (::SHGetMalloc(&pMalloc) == NOERROR)
{
pMalloc->Free(pidl);
pMalloc->Release();
}
}
}
/* virtual */
int
CDirBrowseDlg::DoModal()
/*++
Routine Description:
Display the browser dialog, and fill in the selected directory path.
Arguments:
None
Return Value:
IDOK if the OK button was pressed, IDCANCEL otherwise.
--*/
{
BOOL fSelectionMade = FALSE;
//
// Get the Shell's default allocator
//
LPMALLOC pMalloc;
if (::SHGetMalloc(&pMalloc) == NOERROR)
{
LPITEMIDLIST pidl;
if ((pidl = ::SHBrowseForFolder(&m_bi)) != NULL)
{
if (::SHGetPathFromIDList(pidl, m_szBuffer))
{
fSelectionMade = TRUE;
}
else
{
//
// OK Pressed, but no path found
//
::AfxMessageBox(IDS_BAD_BROWSE);
}
//
// Free the PIDL allocated by SHBrowseForFolder.
//
pMalloc->Free(pidl);
}
//
// Release the shell's allocator.
//
pMalloc->Release();
}
return fSelectionMade ? IDOK : IDCANCEL;
}
LPCTSTR
CDirBrowseDlg::GetFullPath(
OUT CString & strName,
IN BOOL fConvertToUNC
) const
/*++
Routine Description:
Get the full path selected. Optionally allow a remote path to be
converted to a UNC path.
Arguments:
CString & strName : String in which to return the directory path
BOOL fConvertToUNC : If TRUE, then if the drive selected is a network
drive, convert the path to a UNC path.
Return Value:
A pointer to the directory path string or NULL in case of error.
Notes:
This function should be called only after the dialog has been dismissed.
--*/
{
LPCTSTR lp = NULL;
try
{
strName = m_szBuffer;
lp = strName;
if (fConvertToUNC && lp != NULL)
{
//
// If it's network drive, convert it to a UNC path
//
CString strDrive, strUNC;
if (IsNetworkPath(strName, &strDrive, &strUNC))
{
strUNC += (lp + 2);
strName = strUNC;
}
/*
ASSERT(strName[1] == _T(':'));
if (strName[1] == _T(':'))
{
TCHAR szDrive[] = _T("?:");
//
// Fill in actual drive letter
//
szDrive[0] = strName[0];
if (::GetDriveType(szDrive) == DRIVE_REMOTE)
{
//
// Yes, it's remote. Replace drive letter
// with UNC path
//
TCHAR szUNC[_MAX_PATH + 1];
DWORD dwSize = _MAX_PATH;
TRACEEOLID("Converting drive path to UNC");
if (::WNetGetConnection(szDrive,
szUNC, &dwSize) == NO_ERROR)
{
::_tcscat(szUNC, lp + 2);
strName = szUNC;
}
}
}
*/
lp = strName;
}
}
catch(CMemoryException * e)
{
TRACEEOLID("!!!exception getting path");
strName.Empty();
e->ReportError();
e->Delete();
}
return lp;
}
#if 0
// ***************************************************************************
// * *
// * The code below is pre-WIN95 shell directory browsing. It is OBSOLETE *
// * *
// ***************************************************************************
//
// new look commdlg style (not defined on older systems)
//
#ifndef OFN_EXPLORER
#define OFN_EXPLORER 0x00080000
#endif // OFN_EXPLORER
#ifndef _COMSTATIC
//
// Externally available DLL handle
//
extern HINSTANCE hDLLInstance;
#endif // _COMSTATIC
CDirBrowseDlg::CDirBrowseDlg(
IN CWnd * pParent OPTIONAL,
IN LPCTSTR lpszInitialDir OPTIONAL,
IN BOOL bOpenFileDialog,
IN LPCTSTR lpszDefExt OPTIONAL,
IN DWORD dwFlags,
IN LPCTSTR lpszFilter OPTIONAL
)
/*++
Routine Description:
Constructor for directory browser dialog
Arguments:
CWnd * pParent : Parent window or NULL
LPCTSTR lpszInitialDir : Initial directory, or NULL for current directory
BOOL bOpenFileDialog : TRUE for open dialog, FALSE for save dialog
LPCTSTR lpszDefExt : Default extention string or NULL
DWORD dwFlags : OPENFILE flags
LPCTSTR lpszFilter : File filters
Return Value:
N/A
--*/
//
// Use a dummy filename here to allow CFileOpenDialog to
// dismiss itself. If this matches an existing directory
// name we're in trouble, so make that an unlikely event.
// It would be nice if there were a file name that
// cannot exist as a directory name.
//
: CFileDialog(
bOpenFileDialog,
lpszDefExt,
_T(" JU$NK#\t^"),
dwFlags,
lpszFilter,
pParent
),
m_strNewDirectoryName()
{
#if 0 // Keep Class Wizard happy
//{{AFX_DATA_INIT(CDirBrowseDlg)
m_strNewDirectoryName = _T("");
//}}AFX_DATA_INIT
#endif // 0
m_ofn.Flags |= OFN_ENABLETEMPLATE | OFN_NONETWORKBUTTON;
#ifdef _COMSTATIC
m_ofn.hInstance = ::AfxGetResourceHandle();
#else
m_ofn.hInstance = hDLLInstance;
#endif // _COMSTATIC
m_ofn.lpstrInitialDir = lpszInitialDir;
m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_DIRBROWSE);
//
// Explicitly re-set the explorer flag which is set by
// default
//
m_ofn.Flags &= (~OFN_EXPLORER);
}
CDirBrowseDlg::~CDirBrowseDlg()
/*++
Routine Description:
Destructor for directory browser dialog
Arguments:
N/A
Return Value:
N/A
--*/
{
}
/* protected */
void
CDirBrowseDlg::DoDataExchange(
IN CDataExchange * pDX
)
/*++
Routine Description:
Initialise/Store control data
Arguments:
CDataExchange * pDX - DDX/DDV control structure
Return Value:
None
--*/
{
CFileDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDirBrowseDlg)
DDX_Control(pDX, IDC_EDIT_NEW_DIRECTORY_NAME, m_edit_NewDirectoryName);
DDX_Control(pDX, stc1, m_static_stc1);
DDX_Control(pDX, IDC_STATIC_DIR_NAME, m_static_stc2);
DDX_Text(pDX, IDC_EDIT_NEW_DIRECTORY_NAME, m_strNewDirectoryName);
DDV_MaxChars(pDX, m_strNewDirectoryName, _MAX_PATH);
//}}AFX_DATA_MAP
}
//
// Message Map
//
BEGIN_MESSAGE_MAP(CDirBrowseDlg, CFileDialog)
//{{AFX_MSG_MAP(CDirBrowseDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//
// Message Handlers
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
BOOL
CDirBrowseDlg::OnInitDialog()
/*++
Routine Description:
WM_INITDIALOG handler. Initialize the dialog.
Arguments:
None.
Return Value:
TRUE if no focus is to be set automatically, FALSE if the focus
is already set.
--*/
{
CFileDialog::OnInitDialog();
return TRUE;
}
LPCTSTR
CDirBrowseDlg::GetFullPath(
OUT CString & strName,
IN BOOL fConvertToUNC
) const
/*++
Routine Description:
Get the full path selected.
Arguments:
CString & strName : String in which to return the directory path
BOOL fConvertToUNC : If TRUE, then if the drive selected is a network
drive, convert the path to a UNC path.
Return Value:
A pointer to the directory path string or NULL in case of error.
Notes:
This function should be called only after the dialog has been dismissed.
--*/
{
LPCTSTR lp = NULL;
try
{
m_ofn.lpstrFile[m_ofn.nFileOffset-1] = _T('\0');
strName = m_ofn.lpstrFile;
if (!m_strNewDirectoryName.IsEmpty())
{
//
// Append the name of the newly created directory, unless
// it has a colon or backslash in it, in which case it is
// treated as a fully qualified path name
//
if (m_strNewDirectoryName.Find(_T(':')) != -1 ||
m_strNewDirectoryName.Find(_T('\\')) != -1)
{
strName = m_strNewDirectoryName;
}
else
{
strName += _T("\\");
strName += m_strNewDirectoryName;
}
}
lp = strName;
if (fConvertToUNC && lp != NULL)
{
//
// If it's network drive, convert it to a UNC path
//
CString strDrive, strUNC;
if (IsNetworkPath(strName, &strDrive, &strUNC))
{
strUNC += (lp + 2);
strName = strUNC;
}
/*
ASSERT(strName[1] == _T(':'));
if (strName[1] == _T(':'))
{
TCHAR szDrive[] = _T("?:");
//
// Fill in actual drive letter
//
szDrive[0] = strName[0];
if (::GetDriveType(szDrive) == DRIVE_REMOTE)
{
//
// Yes, it's remote. Replace drive letter
// with UNC path
//
TCHAR szUNC[_MAX_PATH + 1];
DWORD dwSize = _MAX_PATH;
TRACEEOLID("Converting drive path to UNC");
if (::WNetGetConnection(szDrive,
szUNC, &dwSize) == NO_ERROR)
{
::_tcscat(szUNC, lp + 2);
strName = szUNC;
}
}
}
*/
lp = strName;
}
}
catch(CMemoryException * e)
{
TRACEEOLID("!!!exception getting path");
strName.Empty();
e->ReportError();
e->Delete();
}
return lp;
}
/* protected */
void
CDirBrowseDlg::OnOK()
/*++
Routine Description:
Handler for IDOK. Called when the OK button has been pressed.
At this point, set the directory path string to the selected
string. If a new directory is entered, create it now. Do not
dismiss the dialog if the path is invalid.
Arguments:
None
Return Value:
None
--*/
{
//
// Update control data
//
if (UpdateData())
{
//
// If a new directory name was entered, create it
// here.
//
if (!m_strNewDirectoryName.IsEmpty())
{
if (!::CreateDirectory(m_strNewDirectoryName, NULL))
{
//
// Failed to create the directory -- let the user
// know why, and don't dismiss the dialog box
//
::DisplayMessage(::GetLastError());
m_edit_NewDirectoryName.SetSel(0,-1);
return;
}
}
//
// Dismiss the dialog.
//
CFileDialog::OnOK();
}
}
#endif // 0 (Obsolete)