|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: aceedit.cpp
//
// This file contains the implementation for the advanced ACE editor
// page.
//
//--------------------------------------------------------------------------
#include "aclpriv.h"
#include "sddl.h" // ConvertSidToStringSid
#define PWM_SELECT_PAGE (WM_APP - 1)
//
// Context Help IDs.
//
const static DWORD aAcePermHelpIDs[] = { IDC_ACEE_INHERITWARNING, IDH_NOHELP, IDC_ACEE_NAME_STATIC, IDH_ACEE_PERM_NAME, IDC_ACEE_NAME, IDH_ACEE_PERM_NAME, IDC_ACEE_NAMEBUTTON, IDH_ACEE_PERM_NAMEBUTTON, IDC_ACEE_APPLYONTO_STATIC, IDH_ACEE_PERM_INHERITTYPE, IDC_ACEE_INHERITTYPE, IDH_ACEE_PERM_INHERITTYPE, IDC_ACEE_ACCESS, IDH_ACEE_PERM_LIST, IDC_ACEE_ALLOW, IDH_ACEE_PERM_LIST, IDC_ACEE_DENY, IDH_ACEE_PERM_LIST, IDC_ACEE_LIST, IDH_ACEE_PERM_LIST, IDC_ACEE_INHERITIMMEDIATE, IDH_ACEE_PERM_INHERITIMMEDIATE, IDC_ACEE_CLEAR, IDH_ACEE_PERM_CLEAR, 0, 0 }; const static DWORD aAceAuditHelpIDs[] = { IDC_ACEE_INHERITWARNING, IDH_NOHELP, IDC_ACEE_NAME_STATIC, IDH_ACEE_AUDIT_NAME, IDC_ACEE_NAME, IDH_ACEE_AUDIT_NAME, IDC_ACEE_NAMEBUTTON, IDH_ACEE_AUDIT_NAMEBUTTON, IDC_ACEE_APPLYONTO_STATIC, IDH_ACEE_AUDIT_INHERITTYPE, IDC_ACEE_INHERITTYPE, IDH_ACEE_AUDIT_INHERITTYPE, IDC_ACEE_ACCESS, IDH_ACEE_AUDIT_LIST, IDC_ACEE_ALLOW, IDH_ACEE_AUDIT_LIST, IDC_ACEE_DENY, IDH_ACEE_AUDIT_LIST, IDC_ACEE_LIST, IDH_ACEE_AUDIT_LIST, IDC_ACEE_INHERITIMMEDIATE, IDH_ACEE_AUDIT_INHERITIMMEDIATE, IDC_ACEE_CLEAR, IDH_ACEE_AUDIT_CLEAR, 0, 0 };
class CACEPage : public CSecurityPage { private: PACE m_pAce; HDPA *m_phEntries; PSID m_pSid; DWORD m_siFlags; DWORD *m_pdwResult; GUID m_guidInheritType; BOOL m_fInheritImmediateEnabled; BOOL m_fPreviousImmediateSetting; BOOL m_fReadOnly; BOOL m_fPageDirty; SI_INHERIT_TYPE m_siInheritUnknown; CACEPage *m_pOtherPage; HWND m_hwnd;
public: CACEPage(LPSECURITYINFO psi, SI_PAGE_TYPE siType, PACE pAce, BOOL bReadOnly, DWORD dwFlags, DWORD *pdwResult, HDPA *phEntries); virtual ~CACEPage();
private: virtual BOOL DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
// Prevent propsheet callbacks from reaching the object that invoked us
virtual UINT PSPageCallback(HWND, UINT, LPPROPSHEETPAGE) { return 1; }
void EmptyCheckList(HWND hwndList); LONG CheckPermBoxes(HWND hwndList, PACE pAce, DWORD dwState); LONG InitCheckList(HWND hDlg, PACE pAce); LONG ReInitCheckList(HWND hDlg, HDPA hEntries); VOID DisplayNoControlMessage(HWND hDlg, BOOL bDisplay); void HideInheritedAceWarning(HWND hDlg); void InitDlg(HWND hDlg); BOOL OnChangeName(HWND hDlg); BOOL OnClearAll(HWND hDlg); void HandleSelChange(HWND hDlg, HWND hWnd); LONG OnApply(HWND hDlg, BOOL bClose); HWND m_hwndNoPerm; BOOL IsAclBloated(HWND hDlg); HDPA GetAceList(HWND hDlg); }; typedef class CACEPage *LPACEPAGE;
CACEPage::CACEPage(LPSECURITYINFO psi, SI_PAGE_TYPE siType, PACE pAce, BOOL bReadOnly, DWORD dwFlags, DWORD *pdwResult, HDPA *phEntries) : CSecurityPage(psi, siType), m_pAce(pAce), m_fReadOnly(bReadOnly), m_siFlags(dwFlags), m_pdwResult(pdwResult), m_phEntries(phEntries), m_hwndNoPerm(NULL),m_pOtherPage(NULL) { if (m_pdwResult) *m_pdwResult = 0; }
CACEPage::~CACEPage() { if (m_pSid) LocalFree(m_pSid); if(m_hwndNoPerm) DestroyWindow(m_hwndNoPerm); }
void CACEPage::EmptyCheckList(HWND hwndList) { SendMessage(hwndList, CLM_RESETCONTENT, 0, 0); }
LONG CACEPage::CheckPermBoxes(HWND hwndList, PACE pAce, DWORD dwState) { LONG nLastChecked = -1; UINT cItems; BOOL bColumnAllow = FALSE; BOOL bColumnDeny = FALSE;
//
// Check all boxes that correspond to a particular ACE
//
if (hwndList == NULL || pAce == NULL) return -1;
if (pAce->AceFlags & INHERITED_ACE) dwState |= CLST_DISABLED;
if (m_siPageType == SI_PAGE_ADVPERM) { // Only check one column (either allow or deny)
if (IsEqualACEType(pAce->AceType, ACCESS_ALLOWED_ACE_TYPE)) bColumnAllow = TRUE; // Access allowed
else if (IsEqualACEType(pAce->AceType, ACCESS_DENIED_ACE_TYPE)) bColumnDeny = TRUE; // Access denied
else return -1; // Bogus ACE
} else if (m_siPageType == SI_PAGE_AUDIT) { // Either or both columns can be checked for audits
if (pAce->AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) bColumnAllow = TRUE; // Audit successful access
if (pAce->AceFlags & FAILED_ACCESS_ACE_FLAG) bColumnDeny = TRUE; // Audit failed access
} else return -1;
cItems = (UINT)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0);
while (cItems > 0) { PSI_ACCESS pAccess;
--cItems; pAccess = (PSI_ACCESS)SendMessage(hwndList, CLM_GETITEMDATA, cItems, 0);
//
// The below expression tests to see if this access mask enables
// this access "rights" line. It could have more bits enabled, but
// as long as it has all of the ones from the pAccess->mask then
// it effectively has that option enabled.
//
if (pAccess && AllFlagsOn(pAce->Mask, pAccess->mask) && (!(pAce->Flags & ACE_OBJECT_TYPE_PRESENT) || IsSameGUID(pAccess->pguid, &pAce->ObjectType))) { WPARAM wItem;
nLastChecked = cItems;
if (bColumnAllow) { wItem = MAKELONG((WORD)cItems, COLUMN_ALLOW); SendMessage(hwndList, CLM_SETSTATE, wItem, (LPARAM)dwState); }
if (bColumnDeny) { wItem = MAKELONG((WORD)cItems, COLUMN_DENY); SendMessage(hwndList, CLM_SETSTATE, wItem, (LPARAM)dwState); } } }
return nLastChecked; }
LONG CACEPage::InitCheckList(HWND hDlg, PACE pAce) { LONG nTopItemChecked; HDPA hList = NULL;
TraceEnter(TRACE_ACEEDIT, "CACEPage::InitCheckList"); TraceAssert(hDlg != NULL);
if (m_siPageType == SI_PAGE_AUDIT) SendDlgItemMessage(hDlg, IDC_ACEE_LIST, CLM_SETCOLUMNWIDTH, 0, 40);
hList = DPA_Create(1); if (hList && pAce) DPA_AppendPtr(hList, pAce->Copy());
nTopItemChecked = ReInitCheckList(hDlg, hList);
if (hList) DestroyDPA(hList);
TraceLeaveValue(nTopItemChecked); }
LONG CACEPage::ReInitCheckList(HWND hDlg, HDPA hEntries) { LONG nTopItemChecked = -1; HWND hwndList; DWORD dwFlags; HRESULT hr; HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
TraceEnter(TRACE_ACEEDIT, "CACEPage::ReInitCheckList"); TraceAssert(hDlg != NULL);
hwndList = GetDlgItem(hDlg, IDC_ACEE_LIST);
EmptyCheckList(hwndList);
dwFlags = SI_ADVANCED;
if (m_siPageType == SI_PAGE_AUDIT) dwFlags |= SI_EDIT_AUDITS;
if (m_siFlags == SI_ACCESS_PROPERTY) dwFlags |= SI_EDIT_PROPERTIES;
//
// Enumerate the permissions and add to the checklist
//
hr = _InitCheckList(hwndList, m_psi, &m_guidInheritType, dwFlags, m_siObjectInfo.hInstance, m_siFlags, NULL); if (SUCCEEDED(hr)) { UINT cItems = (UINT)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0); //
//On object page display the message if number
//cItems is zero.
//
if(m_siFlags == SI_ACCESS_SPECIFIC) DisplayNoControlMessage(hDlg, !cItems);
ULONG cAces = 0; if (hEntries) cAces = DPA_GetPtrCount(hEntries);
//
// Check the appropriate boxes
//
nTopItemChecked = MAXLONG; while (cAces > 0) { PACE_HEADER pAceHeader;
--cAces; pAceHeader = (PACE_HEADER)DPA_FastGetPtr(hEntries, cAces); if (pAceHeader) { CAce Ace(pAceHeader); LONG nTop = CheckPermBoxes(hwndList, &Ace, CLST_CHECKED); if (-1 != nTop) nTopItemChecked = min(nTopItemChecked, nTop); } } if (MAXLONG == nTopItemChecked) nTopItemChecked = -1;
// Make sure the top item checked is scrolled into view.
// (-1 scrolls to the top, same as 0.)
SendMessage(hwndList, CLM_ENSUREVISIBLE, nTopItemChecked, 0);
// Disable all of the boxes if we're in read-only mode
if (m_fReadOnly) SendMessage(hwndList, WM_ENABLE, FALSE, 0); }
SetCursor(hcur); TraceLeaveValue(nTopItemChecked); }
VOID CACEPage::DisplayNoControlMessage(HWND hDlg, BOOL bDisplay) { RECT rc; if(bDisplay) { ShowWindow(m_hwndNoPerm, SW_SHOW); } else { ShowWindow(m_hwndNoPerm, SW_HIDE); } }
void CACEPage::HideInheritedAceWarning(HWND hDlg) // Hides the message informing the user that the current ACE is inherited from
// the parent. Also moves and resizes controls as appropriate.
{ // Array of control IDs to move up
static UINT rgMoveControls[] = { IDC_ACEE_NAME_STATIC, IDC_ACEE_NAME, IDC_ACEE_NAMEBUTTON, IDC_ACEE_APPLYONTO_STATIC, IDC_ACEE_INHERITTYPE, IDC_ACEE_ACCESS, IDC_ACEE_ALLOW, IDC_ACEE_DENY, };
// Get the message window dimensions
HWND hwndControl = GetDlgItem(hDlg, IDC_ACEE_INHERITWARNING); RECT rect; GetWindowRect(hwndControl, &rect);
// We need to move controls up this amount:
int nMoveUpAmount = rect.bottom - rect.top;
// Rather than hide the message window, destroy it altogether so WinHelp
// doesn't confuse it with the "Name:" static during WM_CONTEXTMENU.
DestroyWindow(hwndControl);
// Move each of the controls we need to move up
for (int nControl = 0; nControl < ARRAYSIZE(rgMoveControls); nControl++) { hwndControl = GetDlgItem(hDlg, rgMoveControls[nControl]); GetWindowRect(hwndControl, &rect); MapWindowPoints(NULL, hDlg, (LPPOINT)&rect, 2); SetWindowPos(hwndControl, NULL, rect.left, rect.top - nMoveUpAmount, 0, 0, SWP_NOSIZE | SWP_NOZORDER); }
// Finally, we need to resize the list control, including adjusting its height
hwndControl = GetDlgItem(hDlg, IDC_ACEE_LIST); GetWindowRect(hwndControl, &rect); MapWindowPoints(NULL, hDlg, (LPPOINT)&rect, 2); SetWindowPos(hwndControl, NULL, rect.left, rect.top - nMoveUpAmount, rect.right - rect.left, rect.bottom - (rect.top - nMoveUpAmount), SWP_NOZORDER); }
//
// Default "Apply onto" strings for when GetInheritTypes
// fails or we don't find a matching inherit type.
//
// If desirable, different strings can be created for
// CONTAINER_INHERIT_ACE vs OBJECT_INHERIT_ACE.
//
static const UINT s_aInheritTypes[] = { IDS_THIS_OBJECT_ONLY, // 0 = <no inheritance>
IDS_THIS_OBJECT_AND_SUBOBJECTS, // 1 = OBJECT_INHERIT_ACE
IDS_THIS_OBJECT_AND_SUBOBJECTS, // 2 = CONTAINER_INHERIT_ACE
IDS_THIS_OBJECT_AND_SUBOBJECTS, // 3 = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE
};
// These are used when INHERIT_ONLY_ACE is present
static const UINT s_aInheritOnlyTypes[] = { IDS_INVALID_INHERIT, // 0 = <invalid>
IDS_SUBOBJECTS_ONLY, // 1 = OBJECT_INHERIT_ACE
IDS_SUBOBJECTS_ONLY, // 2 = CONTAINER_INHERIT_ACE
IDS_SUBOBJECTS_ONLY, // 3 = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE
};
static int _AddInheritType(HWND hInheritType, PSI_INHERIT_TYPE psiInheritType, HINSTANCE hInstance) { UINT iIndex; TCHAR szName[MAX_PATH]; LPCTSTR pszName = psiInheritType->pszName;
if (IS_INTRESOURCE(pszName)) { if (LoadString(hInstance, (ULONG)((ULONG_PTR)pszName), szName, ARRAYSIZE(szName)) == 0) { LoadString(::hModule, IDS_UNKNOWN, szName, ARRAYSIZE(szName)); } pszName = szName; }
iIndex = (UINT)SendMessage(hInheritType, CB_ADDSTRING, 0, (LPARAM)pszName);
if (CB_ERR != iIndex) SendMessage(hInheritType, CB_SETITEMDATA, iIndex, (LPARAM)psiInheritType);
return iIndex; }
void CACEPage::InitDlg(HWND hDlg) { #define X_COR 7
#define Y_COR 7
UCHAR AceFlags = 0; PSID pSid = NULL; LPCTSTR pszName = NULL; LPTSTR pszNameT = NULL; HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT)); HRESULT hr;
TraceEnter(TRACE_ACEEDIT, "CACEPage::InitDlg");
//
//Store the hDlg
//
m_hwnd = hDlg; if(m_siFlags == SI_ACCESS_SPECIFIC) { //
//Create a label to show message when no generic
//permissions exist for the object
//
WCHAR szName[1024]; LoadString(::hModule, IDS_NO_OBJECT_PERM, szName, ARRAYSIZE(szName));
RECT rc; GetWindowRect(GetDlgItem(hDlg,IDC_ACEE_LIST),&rc); // Create a new label control
m_hwndNoPerm = CreateWindowEx(0, TEXT("STATIC"), szName, WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP | SS_NOPREFIX, X_COR, Y_COR, rc.right - rc.left - 2*X_COR, rc.bottom - rc.top - 2*Y_COR, GetDlgItem(hDlg,IDC_ACEE_LIST), (HMENU)IntToPtr(0xffff), ::hModule, NULL); // Set the font
SendMessage(m_hwndNoPerm, WM_SETFONT, SendMessage(hDlg, WM_GETFONT, 0, 0), 0); }
if (m_pAce) { AceFlags = m_pAce->AceFlags; m_guidInheritType = m_pAce->InheritedObjectType; pSid = m_pAce->psid; pszName = m_pAce->LookupName(m_siObjectInfo.pszServerName, m_psi2); } else { if (m_siObjectInfo.dwFlags & SI_CONTAINER) AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
pSid = QuerySystemSid(UI_SID_World); }
// Make sure the AceFlags are valid
ACCESS_MASK Mask = 0; m_psi->MapGeneric(&m_guidInheritType, &AceFlags, &Mask);
// Hide the inherit warning and adjust other control positions
if (!(AceFlags & INHERITED_ACE)) HideInheritedAceWarning(hDlg);
// Make a copy of the sid and get the name
if (pSid) { PUSER_LIST pUserList = NULL;
m_pSid = LocalAllocSid(pSid);
if (pszName == NULL) { // This should only happen when m_pAce is NULL and we're
// using UI_SID_World
if (LookupSid(pSid, m_siObjectInfo.pszServerName, m_psi2, &pUserList)) { TraceAssert(NULL != pUserList); TraceAssert(1 == pUserList->cUsers);
if (BuildUserDisplayName(&pszNameT, pUserList->rgUsers[0].pszName, pUserList->rgUsers[0].pszLogonName) || ConvertSidToStringSid(pSid, &pszNameT)) { pszName = pszNameT; } } }
SetDlgItemText(hDlg, IDC_ACEE_NAME, pszName);
if (NULL != pUserList) LocalFree(pUserList); }
// Get the list of permissions and initialize the check boxes
InitCheckList(hDlg, m_pAce);
HWND hInheritType = GetDlgItem(hDlg, IDC_ACEE_INHERITTYPE); HWND hInheritImmed = GetDlgItem(hDlg, IDC_ACEE_INHERITIMMEDIATE);
if (m_siObjectInfo.dwFlags & SI_NO_TREE_APPLY) { ShowWindow(hInheritImmed, SW_HIDE); EnableWindow(hInheritImmed, FALSE); }
//
// Get inherit types from callback
//
ULONG cItems = 0; PSI_INHERIT_TYPE psiInheritType = NULL;
hr = m_psi->GetInheritTypes(&psiInheritType, &cItems); if (SUCCEEDED(hr)) { // Check these inherit bits for a match
DWORD dwInheritMask = INHERIT_ONLY_ACE | ACE_INHERIT_ALL;
// Don't check INHERIT_ONLY_ACE if the ACE inherit type
// matches the current object
if ((m_siObjectInfo.dwFlags & SI_OBJECT_GUID) && IsSameGUID(&m_siObjectInfo.guidObjectType, &m_guidInheritType)) { dwInheritMask &= ~INHERIT_ONLY_ACE; }
//
// Add inherit types to combobox
//
for ( ; cItems > 0; cItems--, psiInheritType++) { UINT iIndex = _AddInheritType(hInheritType, psiInheritType, m_siObjectInfo.hInstance);
// See if this entry matches the incoming ACE
if ((psiInheritType->dwFlags & dwInheritMask) == (ULONG)(AceFlags & dwInheritMask) && IsSameGUID(&m_guidInheritType, psiInheritType->pguid)) { // Got a match, select this entry
SendMessage(hInheritType, CB_SETCURSEL, iIndex, 0); } } }
//
// If GetInheritTypes failed, or we failed to find a match,
// pick a default string and build an appropriate inherit type.
//
if (FAILED(hr) || CB_ERR == SendMessage(hInheritType, CB_GETCURSEL, 0, 0)) { // Pick a default string
UINT ids = IDS_SPECIAL; if (IsNullGUID(&m_guidInheritType)) { if (AceFlags & INHERIT_ONLY_ACE) ids = s_aInheritOnlyTypes[AceFlags & ACE_INHERIT_ALL]; else ids = s_aInheritTypes[AceFlags & ACE_INHERIT_ALL]; }
// Fill in m_siInheritUnknown with the pertinent info
m_siInheritUnknown.pguid = &m_guidInheritType; m_siInheritUnknown.dwFlags = AceFlags & (INHERIT_ONLY_ACE | ACE_INHERIT_ALL); m_siInheritUnknown.pszName = MAKEINTRESOURCE(ids);
// Insert and select it
UINT iIndex = _AddInheritType(hInheritType, &m_siInheritUnknown, ::hModule); SendMessage(hInheritType, CB_SETCURSEL, iIndex, 0);
if (FAILED(hr)) { // GetInheritTypes failed, which means the only entry is the
// default one we just added. Disable the combo.
EnableWindow(hInheritType, FALSE); } }
//
// Select the options which match the incoming ace
//
if (!(AceFlags & (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE))) { SendMessage(hInheritImmed, BM_SETCHECK, BST_UNCHECKED, 0); EnableWindow(hInheritImmed, FALSE); m_fInheritImmediateEnabled = FALSE; m_fPreviousImmediateSetting = BST_UNCHECKED; } else { SendMessage(hInheritImmed, BM_SETCHECK, (AceFlags & NO_PROPAGATE_INHERIT_ACE) ? BST_CHECKED : BST_UNCHECKED, 0); m_fInheritImmediateEnabled = TRUE; }
if (!(m_siObjectInfo.dwFlags & SI_CONTAINER) || m_fReadOnly || (AceFlags & INHERITED_ACE)) { // Disable all inheritance
EnableWindow(hInheritType, FALSE); EnableWindow(hInheritImmed, FALSE); }
if (m_fReadOnly || (AceFlags & INHERITED_ACE)) { // Disable the "change name" and "clear all" buttons
EnableWindow(GetDlgItem(hDlg, IDC_ACEE_NAMEBUTTON), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_ACEE_CLEAR), FALSE); }
PropSheet_QuerySiblings(GetParent(hDlg),0,(LPARAM)this);
LocalFreeString(&pszNameT); SetCursor(hcur);
TraceLeaveVoid(); }
BOOL CACEPage::OnChangeName(HWND hDlg) { PUSER_LIST pUserList = NULL; BOOL bResult = FALSE;
TraceEnter(TRACE_ACEEDIT, "CACEPage::OnChangeName");
if (S_OK == GetUserGroup(hDlg, FALSE, &pUserList)) { TraceAssert(NULL != pUserList); TraceAssert(1 == pUserList->cUsers);
// Free up previous sid
if (m_pSid) LocalFree(m_pSid);
// Copy the new sid
m_pSid = LocalAllocSid(pUserList->rgUsers[0].pSid); if (m_pSid) { SetDlgItemText(hDlg, IDC_ACEE_NAME, pUserList->rgUsers[0].pszName); bResult = TRUE; } LocalFree(pUserList); }
TraceLeaveValue(bResult); }
BOOL CACEPage::OnClearAll(HWND hDlg) { HWND hwndList; ULONG cPermissions;
TraceEnter(TRACE_ACEEDIT, "CACEPage::OnClearAll"); TraceAssert(!m_fReadOnly);
hwndList = GetDlgItem(hDlg, IDC_ACEE_LIST); cPermissions = (ULONG)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0);
while (cPermissions != 0) { WORD wCol = COLUMN_ALLOW;
cPermissions--;
while (wCol == COLUMN_ALLOW || wCol == COLUMN_DENY) { WPARAM wItem = MAKELONG((WORD)cPermissions, wCol);
if (!(CLST_DISABLED & SendMessage(hwndList, CLM_GETSTATE, wItem, 0))) SendMessage(hwndList, CLM_SETSTATE, wItem, CLST_UNCHECKED);
wCol++; } }
TraceLeaveValue(TRUE); }
void CACEPage::HandleSelChange(HWND hDlg, HWND hWnd) // inherit type change
{ PSI_INHERIT_TYPE psiInheritType; BOOL fEnableInheritImmediate = FALSE; const GUID *pguidInheritType = &GUID_NULL;
TraceEnter(TRACE_ACEEDIT, "CACEPage::HandleSelChange");
psiInheritType = (PSI_INHERIT_TYPE)SendMessage(hWnd, CB_GETITEMDATA, SendMessage(hWnd, CB_GETCURSEL, 0, 0), 0);
if (psiInheritType != (PSI_INHERIT_TYPE)CB_ERR && psiInheritType != NULL) { if (psiInheritType->dwFlags & (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE)) fEnableInheritImmediate = TRUE; if( psiInheritType->pguid ) pguidInheritType = psiInheritType->pguid; }
if (fEnableInheritImmediate != m_fInheritImmediateEnabled) { HWND hInheritImmediate = GetDlgItem(hDlg, IDC_ACEE_INHERITIMMEDIATE);
if (fEnableInheritImmediate) { SendMessage(hInheritImmediate, BM_SETCHECK, m_fPreviousImmediateSetting, 0); } else { m_fPreviousImmediateSetting = (BOOL)SendMessage(hInheritImmediate, BM_GETCHECK, 0, 0); SendMessage(hInheritImmediate, BM_SETCHECK, BST_UNCHECKED, 0); }
EnableWindow(hInheritImmediate, fEnableInheritImmediate); m_fInheritImmediateEnabled = fEnableInheritImmediate; }
// If the inherit type GUID has changed, reinitialize the checklist.
if (!IsSameGUID(pguidInheritType, &m_guidInheritType)) { HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT)); HDPA hNewEntries = DPA_Create(4);
if (hNewEntries) { GetAcesFromCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST), m_pSid, m_siPageType == SI_PAGE_ADVPERM, TRUE, 0, // don't care about flags
NULL, // or inherit type here
hNewEntries);
// Save new inherit type and reset the checklist
m_guidInheritType = *pguidInheritType; ReInitCheckList(hDlg, hNewEntries); DestroyDPA(hNewEntries); }
SetCursor(hcur); }
TraceLeaveVoid(); }
void HandleListClick(PNM_CHECKLIST pnmc, SI_PAGE_TYPE siType, BOOL bInheritFlags, HDSA *phAllowUncheckedAccess, HDSA *phDenyUncheckedAccess, BOOL bCustomPresent) { HWND hChkList; UINT iRow; WORD wCol; PSI_ACCESS pAccess; DWORD dwState; BOOL bNullGuid; UINT iRowCompare; PSI_ACCESS pAccessCompare;
TraceEnter(TRACE_MISC, "HandleListClick"); TraceAssert(pnmc != NULL);
hChkList = pnmc->hdr.hwndFrom; iRow = pnmc->iItem; wCol = (WORD)pnmc->iSubItem; // 1 = Allow, 2 = Deny
pAccess = (PSI_ACCESS)pnmc->dwItemData; dwState = pnmc->dwState;
if (pAccess == NULL) TraceLeaveVoid();
if( phAllowUncheckedAccess ) { *phAllowUncheckedAccess = DSA_Create(SIZEOF(PSI_ACCESS), 4); if (*phAllowUncheckedAccess == NULL) { TraceMsg("DSA_Create failed"); TraceLeaveVoid(); } } if( phDenyUncheckedAccess ) { *phDenyUncheckedAccess = DSA_Create(SIZEOF(PSI_ACCESS), 4); if (*phDenyUncheckedAccess == NULL) { TraceMsg("DSA_Create failed"); TraceLeaveVoid(); } }
bNullGuid = IsNullGUID(pAccess->pguid);
iRowCompare = (UINT)SendMessage(hChkList, CLM_GETITEMCOUNT, 0, 0);
//Custom checkbox is handled Separately
if( bCustomPresent ) --iRowCompare;
while (iRowCompare != 0) { WPARAM wItem; DWORD dwStateCompareOriginal; DWORD dwStateCompare; WORD wColCompare; BOOL bSameGuid; BOOL bNullGuidCompare;
--iRowCompare; pAccessCompare = (PSI_ACCESS)SendMessage(hChkList, CLM_GETITEMDATA, iRowCompare, 0);
if (!pAccessCompare) continue;
bSameGuid = IsSameGUID(pAccessCompare->pguid, pAccess->pguid); bNullGuidCompare = IsNullGUID(pAccessCompare->pguid);
// If the GUIDs are incompatible, then we can't do anything
if (!(bSameGuid || bNullGuid || bNullGuidCompare)) continue;
//
// Yukky, complicated mechanism to determine whether to
// turn on or off the allow or deny check marks.
//
// REVIEW: This algorithm of changing check marks based on other
// checkmarks handles a lot of cases, but it doesn't handle a
// two good ones.
//
// (1) If you have a right which implies other rights and you turn,
// it off, then maybe we should turn off all of the implied ones
// too. For example, you turn off change (which is the combination
// of read and write) maybe we should turn off both read and write.
//
// (2) If you turn on all of the component rights of one which
// implies them all, then we should turn on that one (because
// it implies them all).
//
#ifdef NO_RADIOBUTTON_BEHAVIOR
wColCompare = wCol; #else
for (wColCompare = COLUMN_ALLOW; wColCompare <= COLUMN_DENY; wColCompare++) #endif
{ wItem = MAKELONG((WORD)iRowCompare, wColCompare); dwStateCompareOriginal = (DWORD)SendMessage(hChkList, CLM_GETSTATE, wItem, 0);
//
// If the other box is disabled, then it represents an
// inherited right so don't do anything with it.
//
// nb: Depending on NO_RADIOBUTTON_BEHAVIOR, this may continue to the
// for(wColCompare) loop or the while(iRowCompare) loop as appropriate
//
if (dwStateCompareOriginal & CLST_DISABLED) continue;
dwStateCompare = dwStateCompareOriginal;
if (dwState & CLST_CHECKED) { if (wCol == wColCompare) { //
// If this right implies some other right,
// then turn it on too.
//
if ((bSameGuid || bNullGuid) && AllFlagsOn(pAccess->mask, pAccessCompare->mask)) { if (!bInheritFlags || AllFlagsOn(pAccess->dwFlags & ACE_INHERIT_ALL, pAccessCompare->dwFlags & ACE_INHERIT_ALL)) { dwStateCompare |= CLST_CHECKED; } } } else { #ifndef NO_RADIOBUTTON_BEHAVIOR
//
// If this right implies or is implied by some other
// right in the other column, then turn it off.
//
if ( (siType == SI_PAGE_PERM || siType == SI_PAGE_ADVPERM) && (((bSameGuid || bNullGuid) && AllFlagsOn(pAccess->mask, pAccessCompare->mask)) || ((bSameGuid || bNullGuidCompare) && AllFlagsOn(pAccessCompare->mask, pAccess->mask))) ) { if (!bInheritFlags || (AllFlagsOn(pAccessCompare->dwFlags & ACE_INHERIT_ALL, pAccess->dwFlags & ACE_INHERIT_ALL) || AllFlagsOn(pAccess->dwFlags & ACE_INHERIT_ALL, pAccessCompare->dwFlags & ACE_INHERIT_ALL)) ) { dwStateCompare &= ~(CLST_CHECKED); } } #endif
} } else { if (wCol == wColCompare) { //
// If this right is implied by some other right, then
// turn it off too.
//
if ((bSameGuid || bNullGuidCompare) && AllFlagsOn(pAccessCompare->mask, pAccess->mask)) { if (!bInheritFlags || AllFlagsOn(pAccessCompare->dwFlags & ACE_INHERIT_ALL, pAccess->dwFlags & ACE_INHERIT_ALL)) { dwStateCompare &= ~(CLST_CHECKED); } } } }
if (dwStateCompareOriginal != dwStateCompare) { SendMessage(hChkList, CLM_SETSTATE, wItem, (LPARAM)dwStateCompare); //If a checkbox was intially checked and and now unchecked, add to
//h[Allow|Deny]UncheckedAccess.
if( dwStateCompareOriginal & CLST_CHECKED && !(dwStateCompare & CLST_CHECKED) ) { if( phDenyUncheckedAccess && ( wColCompare == COLUMN_DENY ) ) DSA_AppendItem(*phDenyUncheckedAccess, &pAccessCompare); if( phAllowUncheckedAccess && ( wColCompare == COLUMN_ALLOW ) ) DSA_AppendItem(*phAllowUncheckedAccess, &pAccessCompare); }
} } }
TraceLeaveVoid(); }
UINT GetAcesFromCheckList(HWND hChkList, PSID pSid, // All aces get this SID
BOOL fPerm, // Create ACCESS or AUDIT aces?
BOOL fAceFlagsProvided, // Use uAceFlagsAll instead of pAccess->dwFlags
UCHAR uAceFlagsAll, // All aces get these flags
const GUID *pInheritGUID, // All aces get this inherit GUID
HDPA hEntries) // Store new aces here
{ UINT cCheckRows; UINT iCheckRow; UINT cbSidSize; UINT iCount; BOOL bInheritTypePresent = FALSE;
TraceEnter(TRACE_MISC, "GetAcesFromCheckList"); TraceAssert(hChkList != NULL); TraceAssert(pSid != NULL); TraceAssert(hEntries != NULL);
cbSidSize = GetLengthSid(pSid);
if (pInheritGUID == NULL) pInheritGUID = &GUID_NULL; else if (!IsNullGUID(pInheritGUID)) bInheritTypePresent = TRUE;
//
// First clear out the old HDPA
//
iCount = DPA_GetPtrCount(hEntries); while (iCount != 0) { --iCount; LocalFree(DPA_FastGetPtr(hEntries, iCount)); DPA_DeletePtr(hEntries, iCount); }
cCheckRows = (UINT)SendMessage(hChkList, CLM_GETITEMCOUNT, 0, 0); for (iCheckRow = 0; iCheckRow < cCheckRows; iCheckRow++) { PSI_ACCESS pAccess; DWORD dwObjectFlagsNew; WORD wCol; UCHAR uAceFlagsNew;
pAccess = (PSI_ACCESS)SendMessage(hChkList, CLM_GETITEMDATA, iCheckRow, 0);
uAceFlagsNew = (UCHAR)(fAceFlagsProvided ? uAceFlagsAll : pAccess->dwFlags);
dwObjectFlagsNew = 0; if (!IsNullGUID(pAccess->pguid)) dwObjectFlagsNew |= ACE_OBJECT_TYPE_PRESENT;
if (bInheritTypePresent) dwObjectFlagsNew |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
wCol = COLUMN_ALLOW; while (wCol == COLUMN_ALLOW || wCol == COLUMN_DENY) { WPARAM wItem; DWORD dwState;
wItem = MAKELONG((WORD)iCheckRow, wCol); dwState = (DWORD)SendMessage(hChkList, CLM_GETSTATE, wItem, 0);
if ((dwState & CLST_CHECKED) && !(dwState & CLST_DISABLED)) { //
// Ok, time to make an ACE for this check mark, see if we
// can merge it into an already existing ACE, or whether we
// we need to create a new entry
//
UCHAR uAceTypeNew; DWORD dwMaskNew = pAccess->mask; UINT cbSize = SIZEOF(KNOWN_ACE);
if (fPerm) { if (wCol == COLUMN_ALLOW) uAceTypeNew = ACCESS_ALLOWED_ACE_TYPE; else uAceTypeNew = ACCESS_DENIED_ACE_TYPE; } else { uAceTypeNew = SYSTEM_AUDIT_ACE_TYPE; uAceFlagsNew &= ~(SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG);
if (wCol == COLUMN_ALLOW) uAceFlagsNew |= SUCCESSFUL_ACCESS_ACE_FLAG; else uAceFlagsNew |= FAILED_ACCESS_ACE_FLAG; }
if (dwObjectFlagsNew != 0) { uAceTypeNew += (ACCESS_ALLOWED_OBJECT_ACE_TYPE - ACCESS_ALLOWED_ACE_TYPE); cbSize = SIZEOF(KNOWN_OBJECT_ACE);
if (dwObjectFlagsNew & ACE_OBJECT_TYPE_PRESENT) cbSize += SIZEOF(GUID);
if (dwObjectFlagsNew & ACE_INHERITED_OBJECT_TYPE_PRESENT) cbSize += SIZEOF(GUID); }
cbSize += cbSidSize - SIZEOF(ULONG);
//
// See if it exists
//
iCount = DPA_GetPtrCount(hEntries); while(iCount != 0) { PACE_HEADER pAce; BOOL bObjectTypePresent = FALSE; const GUID *pObjectType = NULL;
--iCount; pAce = (PACE_HEADER)DPA_FastGetPtr(hEntries, iCount);
if (IsObjectAceType(pAce)) pObjectType = RtlObjectAceObjectType(pAce);
if (!pObjectType) pObjectType = &GUID_NULL; else bObjectTypePresent = TRUE;
//
// Test the new ACE against each existing ACE to see if
// we can combine them.
//
if (IsEqualACEType(pAce->AceType, uAceTypeNew)) { DWORD dwMergeFlags = 0; DWORD dwMergeStatus; DWORD dwMergeResult;
if (dwObjectFlagsNew & ACE_OBJECT_TYPE_PRESENT) dwMergeFlags |= MF_OBJECT_TYPE_1_PRESENT;
if (bObjectTypePresent) dwMergeFlags |= MF_OBJECT_TYPE_2_PRESENT;
if (!(dwMergeFlags & (MF_OBJECT_TYPE_1_PRESENT | MF_OBJECT_TYPE_2_PRESENT))) { // Neither are present, so they are the same
dwMergeFlags |= MF_OBJECT_TYPE_EQUAL; } else if (IsSameGUID(pAccess->pguid, pObjectType)) dwMergeFlags |= MF_OBJECT_TYPE_EQUAL;
if (!fPerm) dwMergeFlags |= MF_AUDIT_ACE_TYPE;
dwMergeStatus = MergeAceHelper(uAceFlagsNew, dwMaskNew, pAce->AceFlags, ((PKNOWN_ACE)pAce)->Mask, dwMergeFlags, &dwMergeResult);
if (dwMergeStatus == MERGE_MODIFIED_FLAGS) { uAceFlagsNew = (UCHAR)dwMergeResult; dwMergeStatus = MERGE_OK_1; } else if (dwMergeStatus == MERGE_MODIFIED_MASK) { dwMaskNew = dwMergeResult; dwMergeStatus = MERGE_OK_1; }
if (dwMergeStatus == MERGE_OK_1) { //
// The new ACE implies the existing ACE, so
// the existing one can be removed.
//
LocalFree(pAce); DPA_DeletePtr(hEntries, iCount); //
// Keep looking. Maybe we can remove some more entries
// before adding the new one.
//
} else if (dwMergeStatus == MERGE_OK_2) { iCount = 1; // non-zero for match found
break; } } }
//
// Otherwise, add it
//
if (iCount == 0) { PACE_HEADER pAce = (PACE_HEADER)LocalAlloc(LPTR, cbSize);
if (pAce) { PSID pSidT;
pAce->AceType = uAceTypeNew; pAce->AceFlags = uAceFlagsNew; pAce->AceSize = (USHORT)cbSize; ((PKNOWN_ACE)pAce)->Mask = dwMaskNew; pSidT = &((PKNOWN_ACE)pAce)->SidStart;
if (dwObjectFlagsNew != 0) { GUID *pGuid;
((PKNOWN_OBJECT_ACE)pAce)->Flags = dwObjectFlagsNew;
pGuid = RtlObjectAceObjectType(pAce); if (pGuid) { if (pAccess->pguid) *pGuid = *pAccess->pguid; else *pGuid = GUID_NULL; }
pGuid = RtlObjectAceInheritedObjectType(pAce); if (pGuid) *pGuid = *pInheritGUID;
pSidT = RtlObjectAceSid(pAce); }
CopyMemory(pSidT, pSid, cbSidSize); DPA_AppendPtr(hEntries, pAce); } } }
wCol++; } }
iCount = DPA_GetPtrCount(hEntries); TraceLeaveValue(iCount); }
LONG CACEPage::OnApply(HWND hDlg, BOOL /*bClose*/) { const GUID *pInheritGUID; UCHAR uAceFlagsNew = 0; HDPA hEntries; BOOL bAclBloated = FALSE; //
//If this page is property page and user has not clicked on
//the object page, aclbloat must be checked from this page
//only.
//
if((m_siFlags == SI_ACCESS_PROPERTY) && !m_pOtherPage) bAclBloated = IsAclBloated(hDlg);
if(m_siFlags != SI_ACCESS_PROPERTY) bAclBloated = IsAclBloated(hDlg); if(bAclBloated) return PSNRET_INVALID_NOCHANGEPAGE; if (!m_fPageDirty) return PSNRET_NOERROR;
TraceEnter(TRACE_ACEEDIT, "CACEPage::Apply");
//
// Determine inheritance for containers
//
pInheritGUID = &GUID_NULL; if ((m_siObjectInfo.dwFlags & SI_CONTAINER) != 0) { PSI_INHERIT_TYPE psiInheritType = NULL; HWND hInheritType = GetDlgItem( hDlg, IDC_ACEE_INHERITTYPE);
int iSel = (int)SendMessage(hInheritType, CB_GETCURSEL, 0,0);
if (iSel != CB_ERR) { psiInheritType = (PSI_INHERIT_TYPE)SendMessage(hInheritType, CB_GETITEMDATA, iSel, 0); }
if (psiInheritType != (PSI_INHERIT_TYPE)CB_ERR && psiInheritType != NULL) { pInheritGUID = psiInheritType->pguid; uAceFlagsNew = (UCHAR)(psiInheritType->dwFlags & VALID_INHERIT_FLAGS); } else if (m_pAce) { uAceFlagsNew = m_pAce->AceFlags; }
if (m_fInheritImmediateEnabled) { if (IsDlgButtonChecked(hDlg, IDC_ACEE_INHERITIMMEDIATE) == BST_CHECKED) uAceFlagsNew |= NO_PROPAGATE_INHERIT_ACE; else uAceFlagsNew &= ~NO_PROPAGATE_INHERIT_ACE; } }
if (m_phEntries != NULL) { if (*m_phEntries == NULL) *m_phEntries = DPA_Create(4);
GetAcesFromCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST), m_pSid, m_siPageType == SI_PAGE_ADVPERM, TRUE, uAceFlagsNew, pInheritGUID, *m_phEntries); }
if (m_pdwResult) *m_pdwResult |= (m_siFlags == SI_ACCESS_PROPERTY ? EAE_NEW_PROPERTY_ACE : EAE_NEW_OBJECT_ACE); m_fPageDirty = FALSE;
TraceLeaveValue(PSNRET_NOERROR); }
BOOL CACEPage::IsAclBloated(HWND hDlg) { TraceEnter(TRACE_MISC, "CACEPage::ShowAclBloat"); HDPA hEntries = NULL; HDPA hPropEntries = NULL; BOOL bReturn = FALSE;
hEntries = GetAceList(hDlg);
if(m_pOtherPage) { hPropEntries = m_pOtherPage->GetAceList(m_pOtherPage->m_hwnd); }
CACLBloat bloat(m_psi, m_psi2, m_siPageType, &m_siObjectInfo, hEntries, hPropEntries); if(bloat.IsAclBloated()) bReturn = bloat.DoModalDialog(hDlg);
if(hEntries) DestroyDPA(hEntries);
if(hPropEntries) DestroyDPA(hPropEntries);
return bReturn; }
HDPA CACEPage::GetAceList(HWND hDlg) { TraceEnter(TRACE_ACEEDIT, "CACEPage::GetAceList"); if (!m_fPageDirty) return NULL; //
// Determine inheritance for containers
//
const GUID *pInheritGUID = &GUID_NULL; UCHAR uAceFlagsNew = 0; HDPA hEntries = NULL;
if ((m_siObjectInfo.dwFlags & SI_CONTAINER) != 0) { PSI_INHERIT_TYPE psiInheritType = NULL; HWND hInheritType = GetDlgItem( hDlg, IDC_ACEE_INHERITTYPE);
int iSel = (int)SendMessage(hInheritType, CB_GETCURSEL, 0,0);
if (iSel != CB_ERR) { psiInheritType = (PSI_INHERIT_TYPE)SendMessage(hInheritType, CB_GETITEMDATA, iSel, 0); }
if (psiInheritType != (PSI_INHERIT_TYPE)CB_ERR && psiInheritType != NULL) { pInheritGUID = psiInheritType->pguid; uAceFlagsNew = (UCHAR)(psiInheritType->dwFlags & VALID_INHERIT_FLAGS); } else if (m_pAce) { uAceFlagsNew = m_pAce->AceFlags; }
if (m_fInheritImmediateEnabled) { if (IsDlgButtonChecked(hDlg, IDC_ACEE_INHERITIMMEDIATE) == BST_CHECKED) uAceFlagsNew |= NO_PROPAGATE_INHERIT_ACE; else uAceFlagsNew &= ~NO_PROPAGATE_INHERIT_ACE; } }
hEntries = DPA_Create(4);
if(hEntries) { GetAcesFromCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST), m_pSid, m_siPageType == SI_PAGE_ADVPERM, TRUE, uAceFlagsNew, pInheritGUID, hEntries); } return hEntries; }
BOOL CACEPage::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: InitDlg(hDlg); break;
case WM_DESTROY: EmptyCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST)); break;
case PWM_SELECT_PAGE: PropSheet_SetCurSel(GetParent(hDlg), lParam, wParam); break;
case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDC_ACEE_NAMEBUTTON: if (OnChangeName(hDlg)) { PropSheet_Changed(GetParent(hDlg), hDlg); m_fPageDirty = TRUE; } break;
case IDC_ACEE_INHERITTYPE: if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) { HandleSelChange(hDlg, (HWND)lParam); PropSheet_Changed(GetParent(hDlg), hDlg); m_fPageDirty = TRUE; } break;
case IDC_ACEE_INHERITIMMEDIATE: if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED) { PropSheet_Changed(GetParent(hDlg), hDlg); m_fPageDirty = TRUE; } break;
case IDC_ACEE_CLEAR: if (OnClearAll(hDlg)) { PropSheet_Changed(GetParent(hDlg), hDlg); m_fPageDirty = TRUE; } break;
default: return FALSE; } break;
case WM_NOTIFY: switch (((NMHDR *)lParam)->code) { case CLN_CLICK: if (lParam) { HandleListClick((PNM_CHECKLIST)lParam, m_siPageType, FALSE); PropSheet_Changed(GetParent(hDlg), hDlg); m_fPageDirty = TRUE; } break;
case CLN_GETCOLUMNDESC: { PNM_CHECKLIST pnmc = (PNM_CHECKLIST)lParam; GetDlgItemText(hDlg, IDC_ACEE_ALLOW - 1 + pnmc->iSubItem, pnmc->pszText, pnmc->cchTextMax); } break;
case PSN_APPLY: SetWindowLongPtr(hDlg, DWLP_MSGRESULT, OnApply(hDlg, (BOOL)(((LPPSHNOTIFY)lParam)->lParam))); break;
} break;
case PSM_QUERYSIBLINGS: { BOOL bSendQuery = !m_pOtherPage; if(this != (CACEPage*)lParam) m_pOtherPage = (CACEPage*)lParam;
if(bSendQuery) PostMessage(GetParent(hDlg),PSM_QUERYSIBLINGS,0,(LPARAM)this); }
break;
case WM_HELP: if (IsWindowEnabled(hDlg)) { const DWORD *pdwHelpIDs = aAcePermHelpIDs;
if (m_siPageType == SI_PAGE_AUDIT) pdwHelpIDs = aAceAuditHelpIDs;
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, c_szAcluiHelpFile, HELP_WM_HELP, (DWORD_PTR)pdwHelpIDs); } break;
case WM_CONTEXTMENU: if (IsWindowEnabled(hDlg)) { HWND hwnd = (HWND)wParam; const DWORD *pdwHelpIDs = aAcePermHelpIDs;
if (m_siPageType == SI_PAGE_AUDIT) pdwHelpIDs = aAceAuditHelpIDs;
//
// Some of the checkboxes may be scrolled out of view, but
// they are still detected by WinHelp, so we jump through
// a few extra hoops here.
//
if (hwnd == hDlg) { POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
ScreenToClient(hDlg, &pt); hwnd = ChildWindowFromPoint(hDlg, pt); if (hDlg == hwnd) break; }
//
// WinHelp looks for child windows, but we don't have help id's
// for the permission checkboxes. If the request is for the
// checklist window, fake out WinHelp by referring to one of
// the static labels just above the list.
//
if (GetDlgCtrlID(hwnd) == IDC_ACEE_LIST) hwnd = GetWindow((HWND)wParam, GW_HWNDPREV); // Static label "Deny"
WinHelp(hwnd, c_szAcluiHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)pdwHelpIDs); } break;
default: return FALSE; }
return TRUE; }
HPROPSHEETPAGE CreateACEPage(LPSECURITYINFO psi, SI_PAGE_TYPE siType, PACE pAce, BOOL bReadOnly, DWORD dwFlags, DWORD *pdwResult, HDPA *phEntries) { HPROPSHEETPAGE hPage = NULL; LPCTSTR pszTitle = NULL; LPACEPAGE pPage;
TraceEnter(TRACE_ACEEDIT, "CreateACEPage"); TraceAssert(psi != NULL); TraceAssert(phEntries != NULL);
pPage = new CACEPage(psi, siType, pAce, bReadOnly, dwFlags, pdwResult, phEntries); if (pPage) { int iDlgTemplate = IDD_ACEENTRY_PERM_PAGE;
if (siType == SI_PAGE_AUDIT) iDlgTemplate = IDD_ACEENTRY_AUDIT_PAGE;
if (dwFlags == SI_ACCESS_PROPERTY) pszTitle = MAKEINTRESOURCE(IDS_ACEE_PROPERTY_TITLE);
hPage = pPage->CreatePropSheetPage(MAKEINTRESOURCE(iDlgTemplate), pszTitle); }
TraceLeaveValue(hPage); }
BOOL EditACEEntry(HWND hwndOwner, LPSECURITYINFO psi, PACE pAce, SI_PAGE_TYPE siType, LPCTSTR pszObjectName, BOOL bReadOnly, DWORD *pdwResult, HDPA *phEntries, HDPA *phPropertyEntries, UINT nStartPage) { HPROPSHEETPAGE hPage[2]; UINT cPages = 0; BOOL bResult = FALSE;
TraceEnter(TRACE_ACEEDIT, "EditACEEntry"); TraceAssert(psi != NULL);
if (phEntries) { hPage[cPages] = CreateACEPage(psi, siType, pAce, bReadOnly, SI_ACCESS_SPECIFIC, pdwResult, phEntries); if (hPage[cPages]) cPages++; }
if (phPropertyEntries) { hPage[cPages] = CreateACEPage(psi, siType, pAce, bReadOnly, SI_ACCESS_PROPERTY, pdwResult, phPropertyEntries); if (hPage[cPages]) cPages++; }
if (cPages) { // Build dialog title string
LPTSTR pszCaption = NULL; FormatStringID(&pszCaption, ::hModule, siType == SI_PAGE_AUDIT ? IDS_ACEE_AUDIT_TITLE : IDS_ACEE_PERM_TITLE, pszObjectName);
PROPSHEETHEADER psh; psh.dwSize = SIZEOF(psh); psh.dwFlags = PSH_DEFAULT | PSH_NOAPPLYNOW; psh.hwndParent = hwndOwner; psh.hInstance = ::hModule; psh.pszCaption = pszCaption; psh.nPages = cPages; psh.nStartPage = 0; psh.phpage = &hPage[0];
if (nStartPage < cPages) psh.nStartPage = nStartPage;
bResult = (PropertySheet(&psh) == IDOK);
LocalFreeString(&pszCaption); }
TraceLeaveValue(bResult); }
|