|
|
/*++
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 = NULL; 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;
ULONG ulNoChars;
ulNoChars = wcslen( (LPCWSTR)szGroup )+1; szWindowText = new WCHAR[ulNoChars]; if ( szWindowText == NULL ) { goto KillFocusEnd; } //get the account name from the window
HRESULT hr;
hr = StringCchCopy (szWindowText, ulNoChars, (LPCWSTR) szGroup); ASSERT(SUCCEEDED(hr));
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
LocalFree(Sid); Sid = (PSID) LocalAlloc (LPTR, 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:
LocalFree(Sid); if ( szWindowText != NULL ) { delete [] szWindowText; } 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; }
|