569 lines
15 KiB
C++
569 lines
15 KiB
C++
/*++
|
|
|
|
Microsoft Windows
|
|
Copyright (C) Microsoft Corporation, 1981 - 1998
|
|
|
|
Module Name:
|
|
|
|
secpath.cxx
|
|
|
|
Abstract:
|
|
|
|
this file contains the code for the dialog that is used for associating
|
|
security groups with paths.
|
|
|
|
Author:
|
|
|
|
Rahul Thombre (RahulTh) 4/14/1998
|
|
|
|
Revision History:
|
|
|
|
4/14/1998 RahulTh
|
|
|
|
Created this module.
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
//
|
|
//mapping between help ids and controls ids for this dialog
|
|
//
|
|
const DWORD g_aHelpIDMap_IDD_SECPATH[] =
|
|
{
|
|
IDC_SECPATH_ICON, IDH_DISABLEHELP,
|
|
IDC_SECPATH_DESC, IDH_DISABLEHELP,
|
|
IDC_SECPATH_SECGROUP, IDH_DISABLEHELP,
|
|
IDC_EDIT_SECGROUP, IDH_EDIT_SECGROUP,
|
|
IDC_BROWSE_SECGROUP, IDH_BROWSE_SECGROUP,
|
|
IDC_SECPATH_TARGET, IDH_DISABLEHELP,
|
|
0, 0
|
|
};
|
|
|
|
///////////////////////////
|
|
/// Construction
|
|
|
|
CSecGroupPath::CSecGroupPath (CWnd * pParent,
|
|
UINT cookie,
|
|
LPCTSTR szFolderName,
|
|
LPCTSTR szGroupName /*=NULL*/,
|
|
LPCTSTR szGroupSidStr /*=NULL*/,
|
|
LPCTSTR szTarget /*= NULL*/)
|
|
: CDialog(CSecGroupPath::IDD, pParent), m_redirPath (cookie), m_cookie (cookie)
|
|
{
|
|
m_szFolderName = szFolderName;
|
|
m_szGroup = szGroupName;
|
|
m_szSidStr = szGroupSidStr;
|
|
m_szTarget = szTarget;
|
|
if (! m_szTarget.IsEmpty())
|
|
{
|
|
m_szTarget.TrimLeft();
|
|
m_szTarget.TrimRight();
|
|
m_szTarget.TrimRight(L'\\');
|
|
}
|
|
m_bPathValid = FALSE;
|
|
m_iCurrType = -1;
|
|
}
|
|
|
|
/////////////////////////
|
|
///Overrides
|
|
|
|
void CSecGroupPath::DoDataExchange (CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CSecGroupPath)
|
|
DDX_Control(pDX, IDC_EDIT_SECGROUP, m_EditSecGroup);
|
|
DDX_Control(pDX, IDC_BROWSE_SECGROUP, m_btnBrowseSecGroup);
|
|
DDX_Control(pDX, IDC_SECPATH_PLACEHOLDER, m_placeHolder);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
/////////////////////
|
|
/// Message maps
|
|
BEGIN_MESSAGE_MAP(CSecGroupPath, CDialog)
|
|
//{{AFX_MSG_MAP(CSecGroupPath)
|
|
ON_BN_CLICKED (IDC_BROWSE_SECGROUP, OnBrowseGroups)
|
|
ON_EN_UPDATE (IDC_EDIT_SECGROUP, OnSecGroupUpdate)
|
|
ON_EN_KILLFOCUS (IDC_EDIT_SECGROUP, OnSecGroupKillFocus)
|
|
ON_MESSAGE (WM_PATH_TWEAKED, OnPathTweak)
|
|
ON_MESSAGE (WM_HELP, OnHelp)
|
|
ON_MESSAGE (WM_CONTEXTMENU, OnContextMenu)
|
|
//}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
BOOL CSecGroupPath::OnInitDialog ()
|
|
{
|
|
CError error (this);
|
|
|
|
CDialog::OnInitDialog();
|
|
|
|
//
|
|
// Make sure that the supplied path is parseable into one of the known
|
|
// types
|
|
//
|
|
if (! m_szTarget.IsEmpty())
|
|
m_redirPath.Load ((LPCTSTR) m_szTarget); // This will always succeed if m_szTarget is not empty
|
|
|
|
m_pathChooser.Instantiate (m_cookie,
|
|
this,
|
|
&m_placeHolder,
|
|
(const CRedirPath *) &m_redirPath,
|
|
SWP_SHOWWINDOW
|
|
);
|
|
|
|
m_EditSecGroup.SetWindowText (m_szGroup);
|
|
m_EditSecGroup.SetSel (0, -1, FALSE);
|
|
m_EditSecGroup.SetFocus();
|
|
SetOKState();
|
|
|
|
return FALSE; //returning FALSE since we are setting the focus to the edit box
|
|
}
|
|
|
|
void CSecGroupPath::OnOK ()
|
|
{
|
|
CError error(this);
|
|
CString szRoot;
|
|
CString szSuffix;
|
|
CRedirPath newPath (m_cookie);
|
|
BOOL bStatus = TRUE;
|
|
UINT pathType;
|
|
|
|
//first check if we have a valid group.
|
|
OnSecGroupKillFocus();
|
|
|
|
//if the target is not a UNC path, try to convert it to one.
|
|
m_pathChooser.OnRootKillFocus();
|
|
|
|
if (!m_fValidSid)
|
|
{
|
|
error.ShowMessage (IDS_NOSECURITY_INFO);
|
|
return;
|
|
}
|
|
|
|
m_EditSecGroup.GetWindowText (m_szGroup);
|
|
m_szGroup.TrimLeft();
|
|
m_szGroup.TrimRight();
|
|
|
|
m_szSidStr.TrimLeft();
|
|
m_szSidStr.TrimRight();
|
|
m_szSidStr.MakeLower();
|
|
|
|
m_pathChooser.GetRoot (szRoot);
|
|
pathType = m_pathChooser.GetType();
|
|
|
|
bStatus = TRUE;
|
|
if (m_redirPath.IsPathDifferent (pathType, (LPCTSTR)szRoot))
|
|
{
|
|
// The path has changed, so use the new suffix
|
|
newPath.GenerateSuffix (szSuffix, m_cookie, pathType);
|
|
bStatus = newPath.Load (pathType, (LPCTSTR) szRoot, (LPCTSTR) szSuffix);
|
|
if (bStatus)
|
|
newPath.GeneratePath (m_szTarget);
|
|
}
|
|
else
|
|
{
|
|
m_redirPath.GeneratePath (m_szTarget);
|
|
}
|
|
|
|
//check if all the data has been provided.
|
|
if (! bStatus ||
|
|
m_szTarget == TEXT("*") || //this particular check is very important -- see code for CFileInfo::LoadSection to see why
|
|
m_szGroup.IsEmpty())
|
|
{
|
|
error.ShowMessage (IDS_INVALID_GROUPPATH);
|
|
}
|
|
else if (pathType != IDS_USERPROFILE_PATH &&
|
|
! PathIsUNC ((LPCTSTR) m_szTarget)
|
|
)
|
|
{
|
|
error.SetStyle (MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2);
|
|
error.SetTitle (IDS_DEFAULT_WARNING_TITLE);
|
|
if (IDYES == error.ShowMessage (IDS_PATHNOTUNC_WARNING))
|
|
{
|
|
CDialog::OnOK();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CDialog::OnOK();
|
|
}
|
|
}
|
|
|
|
void
|
|
CSecGroupPath::OnCancel (void)
|
|
{
|
|
m_pathChooser.OnCancel();
|
|
CDialog::OnCancel();
|
|
}
|
|
|
|
//browse the security groups
|
|
void CSecGroupPath::OnBrowseGroups ()
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
CError error(this);
|
|
PCWSTR apwszAttribs[] =
|
|
{
|
|
L"ObjectSid"
|
|
};
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
HRESULT hr;
|
|
IDsObjectPicker * pDsObjectPicker = NULL;
|
|
DSOP_INIT_INFO InitInfo;
|
|
const ULONG cbNumScopes = 3;
|
|
DSOP_SCOPE_INIT_INFO ascopes[cbNumScopes];
|
|
IDataObject * pdo = NULL;
|
|
STGMEDIUM stgmedium = {
|
|
TYMED_HGLOBAL,
|
|
NULL
|
|
};
|
|
UINT cf = 0;
|
|
PDS_SELECTION_LIST pDsSelList = NULL;
|
|
FORMATETC formatetc = {
|
|
(CLIPFORMAT)cf,
|
|
NULL,
|
|
DVASPECT_CONTENT,
|
|
-1,
|
|
TYMED_HGLOBAL
|
|
};
|
|
PDS_SELECTION pDsSelection = NULL;
|
|
BOOL bAllocatedStgMedium = FALSE;
|
|
SAFEARRAY * pVariantArr = NULL;
|
|
PSID pSid = NULL;
|
|
CString szDomain;
|
|
CString szAcct;
|
|
SID_NAME_USE eUse;
|
|
|
|
|
|
hr = CoInitialize (NULL);
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
hr = CoCreateInstance (CLSID_DsObjectPicker,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IDsObjectPicker,
|
|
(void **) & pDsObjectPicker
|
|
);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
dwError = IDS_OBJPICK_ERROR;
|
|
goto BrwsGrp_Err;
|
|
}
|
|
|
|
|
|
//Initialize the scopes
|
|
ZeroMemory (ascopes, cbNumScopes * sizeof (DSOP_SCOPE_INIT_INFO));
|
|
|
|
ascopes[0].cbSize = sizeof (DSOP_SCOPE_INIT_INFO);
|
|
ascopes[0].flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN;
|
|
ascopes[0].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE;
|
|
ascopes[0].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_BUILTIN_GROUPS |
|
|
DSOP_FILTER_UNIVERSAL_GROUPS_DL |
|
|
DSOP_FILTER_UNIVERSAL_GROUPS_SE |
|
|
DSOP_FILTER_GLOBAL_GROUPS_DL |
|
|
DSOP_FILTER_GLOBAL_GROUPS_SE;
|
|
ascopes[0].FilterFlags.Uplevel.flNativeModeOnly =
|
|
DSOP_FILTER_DOMAIN_LOCAL_GROUPS_DL |
|
|
DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE;
|
|
|
|
ascopes[1].cbSize = sizeof (DSOP_SCOPE_INIT_INFO);
|
|
ascopes[1].flType = DSOP_SCOPE_TYPE_GLOBAL_CATALOG;
|
|
ascopes[1].FilterFlags.Uplevel.flBothModes =
|
|
ascopes[0].FilterFlags.Uplevel.flBothModes;
|
|
ascopes[1].FilterFlags.Uplevel.flNativeModeOnly =
|
|
ascopes[0].FilterFlags.Uplevel.flNativeModeOnly;
|
|
|
|
ascopes[2].cbSize = sizeof (DSOP_SCOPE_INIT_INFO);
|
|
ascopes[2].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER;
|
|
ascopes[2].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS |
|
|
DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS;
|
|
|
|
//Populate the InitInfo structure that is used to initialize the object
|
|
//picker.
|
|
ZeroMemory (&InitInfo, sizeof (InitInfo));
|
|
|
|
InitInfo.cbSize = sizeof (InitInfo);
|
|
InitInfo.cDsScopeInfos = cbNumScopes;
|
|
InitInfo.aDsScopeInfos = ascopes;
|
|
InitInfo.cAttributesToFetch = 1;
|
|
InitInfo.apwzAttributeNames = apwszAttribs;
|
|
|
|
hr = pDsObjectPicker->Initialize (&InitInfo);
|
|
|
|
if (FAILED (hr))
|
|
{
|
|
dwError = IDS_OBJPICK_ERROR;
|
|
goto BrwsGrp_Err;
|
|
}
|
|
|
|
hr = pDsObjectPicker->InvokeDialog (this->m_hWnd, &pdo);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
dwError = IDS_OBJPICK_ERROR;
|
|
goto BrwsGrp_Err;
|
|
}
|
|
|
|
if (S_FALSE == hr) //the user hit cancel
|
|
goto BrwsGrp_CleanupAndQuit;
|
|
|
|
//if we are here, the user chose, OK, so find out what group was chosen
|
|
cf = RegisterClipboardFormat (CFSTR_DSOP_DS_SELECTION_LIST);
|
|
|
|
if (0 == cf)
|
|
{
|
|
dwError = IDS_NOSECURITY_INFO;
|
|
goto BrwsGrp_Err;
|
|
}
|
|
|
|
//set the clipformat for the formatetc structure
|
|
formatetc.cfFormat = (CLIPFORMAT)cf;
|
|
|
|
hr = pdo->GetData (&formatetc, &stgmedium);
|
|
|
|
if (FAILED (hr) )
|
|
{
|
|
dwError = IDS_NOSECURITY_INFO;
|
|
goto BrwsGrp_Err;
|
|
}
|
|
|
|
bAllocatedStgMedium = TRUE;
|
|
|
|
pDsSelList = (PDS_SELECTION_LIST) GlobalLock (stgmedium.hGlobal);
|
|
|
|
if (NULL == pDsSelList)
|
|
{
|
|
dwError = IDS_NOSECURITY_INFO;
|
|
goto BrwsGrp_Err;
|
|
}
|
|
|
|
|
|
if (!pDsSelList->cItems) //some item must have been selected
|
|
{
|
|
dwError = IDS_NOSECURITY_INFO;
|
|
goto BrwsGrp_Err;
|
|
}
|
|
|
|
pDsSelection = &(pDsSelList->aDsSelection[0]);
|
|
|
|
//we must get the ObjectSid attribute, otherwise we fail
|
|
//so make sure that the attribute has been fetched.
|
|
if (!pDsSelList->cFetchedAttributes ||
|
|
(! (VT_ARRAY & pDsSelection->pvarFetchedAttributes->vt)))
|
|
{
|
|
dwError = IDS_NOSECURITY_INFO;
|
|
goto BrwsGrp_Err;
|
|
}
|
|
|
|
pVariantArr = pDsSelection->pvarFetchedAttributes->parray;
|
|
pSid = (PSID) pVariantArr->pvData;
|
|
|
|
if (STATUS_SUCCESS != GetFriendlyNameFromSid (pSid, szDomain, szAcct, &eUse))
|
|
{
|
|
dwError = IDS_NOSECURITY_INFO;
|
|
goto BrwsGrp_Err;
|
|
}
|
|
|
|
//store away the string representation of this sid
|
|
if (STATUS_SUCCESS != GetStringFromSid(pSid, m_szSidStr))
|
|
goto BrwsGrp_Err;
|
|
|
|
m_szSidStr.MakeLower();
|
|
if (!szDomain.IsEmpty())
|
|
szAcct = szDomain + '\\' + szAcct;
|
|
|
|
m_EditSecGroup.SetWindowText (szAcct);
|
|
m_fValidSid = TRUE;
|
|
|
|
goto BrwsGrp_CleanupAndQuit;
|
|
|
|
BrwsGrp_Err:
|
|
error.ShowMessage (dwError);
|
|
|
|
BrwsGrp_CleanupAndQuit:
|
|
if (pDsSelList)
|
|
GlobalUnlock (stgmedium.hGlobal);
|
|
if (bAllocatedStgMedium)
|
|
ReleaseStgMedium (&stgmedium);
|
|
if (pdo)
|
|
pdo->Release();
|
|
if (pDsObjectPicker)
|
|
pDsObjectPicker->Release ();
|
|
}
|
|
|
|
void CSecGroupPath::SetOKState (void)
|
|
{
|
|
CString szGroup;
|
|
CString szPath;
|
|
BOOL bCheckPath = FALSE;
|
|
|
|
m_EditSecGroup.GetWindowText(szGroup);
|
|
szGroup.TrimLeft();
|
|
szGroup.TrimRight();
|
|
|
|
if (IDS_SPECIFIC_PATH == m_iCurrType ||
|
|
IDS_PERUSER_PATH == m_iCurrType)
|
|
{
|
|
bCheckPath = TRUE;
|
|
m_pathChooser.GetRoot (szPath);
|
|
szPath.TrimLeft();
|
|
szPath.TrimRight();
|
|
szPath.TrimRight(L'\\');
|
|
}
|
|
|
|
if (szGroup.IsEmpty() || (bCheckPath && szPath.IsEmpty()))
|
|
GetDescendantWindow(IDOK, FALSE)->EnableWindow(FALSE);
|
|
else
|
|
GetDescendantWindow(IDOK, FALSE)->EnableWindow(TRUE);
|
|
}
|
|
|
|
void CSecGroupPath::OnSecGroupUpdate()
|
|
{
|
|
//the group in the edit box is about to change.
|
|
//this means we can no longer trust the sid that we may have
|
|
m_fValidSid = FALSE;
|
|
SetOKState();
|
|
}
|
|
|
|
//we try to get a sid and domain for the group specified
|
|
//if we can't, we simply ignore the error and sit tight.
|
|
void CSecGroupPath::OnSecGroupKillFocus()
|
|
{
|
|
BOOL bStatus;
|
|
CString szGroup;
|
|
WCHAR szWindowText[MAX_PATH];
|
|
WCHAR szDom[MAX_PATH];
|
|
DWORD dwDomLen = MAX_PATH;
|
|
WCHAR* szAcct;
|
|
PSID Sid = NULL;
|
|
DWORD dwSidLen = 0;
|
|
SID_NAME_USE eUse;
|
|
DWORD Status;
|
|
CHourglass hourglass; //LookupAccountName takes a while
|
|
BOOL fDomainSupplied = FALSE;
|
|
|
|
|
|
//if we already have a valid sid, there is nothing to worry.
|
|
if (m_fValidSid)
|
|
goto KillFocusEnd;
|
|
|
|
//we don't have a valid sid, so we try to get one from the data in the
|
|
//group box
|
|
m_EditSecGroup.GetWindowText (szGroup);
|
|
szGroup.TrimLeft();
|
|
szGroup.TrimRight();
|
|
|
|
if (szGroup.IsEmpty())
|
|
goto KillFocusEnd;
|
|
|
|
|
|
//get the account name from the window
|
|
wcscpy (szWindowText, (LPCTSTR) szGroup);
|
|
szAcct = wcsrchr (szWindowText, '\\');
|
|
if (!szAcct)
|
|
{
|
|
szAcct = szWindowText;
|
|
}
|
|
else
|
|
{
|
|
*szAcct++ = 0; //advance it so that it now points to the account
|
|
//and szWindowText will now refer to the supplied domain
|
|
fDomainSupplied = TRUE;
|
|
}
|
|
|
|
do
|
|
{
|
|
bStatus = LookupAccountName (NULL, szAcct, Sid, &dwSidLen,
|
|
szDom, &dwDomLen, &eUse);
|
|
|
|
if (!bStatus)
|
|
{
|
|
Status = GetLastError();
|
|
if (ERROR_INSUFFICIENT_BUFFER != Status)
|
|
goto KillFocusEnd; //we just ignore the error for now
|
|
Sid = (PSID) alloca (dwSidLen);
|
|
if (NULL == Sid)
|
|
goto KillFocusEnd; //we just ignore the error for now
|
|
|
|
continue;
|
|
}
|
|
break;
|
|
} while (1);
|
|
|
|
//we have the sid if we are here
|
|
//make sure it represents a group
|
|
switch (eUse)
|
|
{
|
|
case SidTypeGroup:
|
|
case SidTypeWellKnownGroup:
|
|
case SidTypeAlias:
|
|
break;
|
|
default:
|
|
goto KillFocusEnd;
|
|
}
|
|
|
|
//also make sure that if a domain was supplied, it matches what we
|
|
//got back
|
|
if (fDomainSupplied && (0 != lstrcmpi (szWindowText, szDom)))
|
|
goto KillFocusEnd;
|
|
|
|
//if we are here, then we have the sid for a group
|
|
if (STATUS_SUCCESS != GetStringFromSid (Sid, m_szSidStr))
|
|
goto KillFocusEnd;
|
|
|
|
//we were finally successful in getting the sid in a string format
|
|
m_szSidStr.MakeLower();
|
|
szGroup = szDom;
|
|
if (!szGroup.IsEmpty())
|
|
szGroup += '\\';
|
|
szGroup += szAcct;
|
|
m_EditSecGroup.SetWindowText ((LPCTSTR) szGroup);
|
|
m_fValidSid = TRUE;
|
|
|
|
KillFocusEnd:
|
|
return;
|
|
}
|
|
|
|
void CSecGroupPath::OnPathTweak (WPARAM wParam, LPARAM lParam)
|
|
{
|
|
m_bPathValid = (BOOL) wParam;
|
|
m_iCurrType = (LONG) lParam;
|
|
|
|
SetOKState();
|
|
}
|
|
|
|
LONG CSecGroupPath::OnHelp (WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LONG lResult = 0;
|
|
CString szHelpFile;
|
|
|
|
szHelpFile.LoadString(IDS_HELP_FILE);
|
|
|
|
::WinHelp((HWND)(((LPHELPINFO)lParam)->hItemHandle),
|
|
(LPCTSTR) szHelpFile,
|
|
HELP_WM_HELP,
|
|
(ULONG_PTR)(LPTSTR)g_aHelpIDMap_IDD_SECPATH);
|
|
|
|
return lResult;
|
|
}
|
|
|
|
LONG CSecGroupPath::OnContextMenu (WPARAM wParam, LPARAM lParam)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetStaticModuleState());
|
|
|
|
LONG lResult = 0;
|
|
CString szHelpFile;
|
|
|
|
szHelpFile.LoadString(IDS_HELP_FILE);
|
|
|
|
::WinHelp((HWND)wParam,
|
|
(LPCTSTR)szHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(ULONG_PTR)(LPVOID)g_aHelpIDMap_IDD_SECPATH);
|
|
|
|
return lResult;
|
|
}
|