windows-nt/Source/XPSP1/NT/ds/security/gina/snapins/fde/secpath.cxx
2020-09-26 16:20:57 +08:00

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;
}