windows-nt/Source/XPSP1/NT/shell/osshell/security/aclui/aclbloat.cpp
2020-09-26 16:20:57 +08:00

736 lines
17 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 2001
//
// File: aclbloat.h
//
// This file contains the implementation of ACLBLOAT class which controls the
// dialog box for aclbloat
//
// Author hiteshr 4th April 2001
//
//--------------------------------------------------------------------------
#include "aclpriv.h"
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::CACLBloat
//
// Synopsis: Constructor
//
//
// History: 04-April 2001 hiteshr Created
//
//---------------------------------------------------------------------------
CACLBloat::CACLBloat(LPSECURITYINFO psi,
LPSECURITYINFO2 psi2,
SI_PAGE_TYPE siPageType,
SI_OBJECT_INFO* psiObjectInfo,
HDPA hEntries,
HDPA hPropEntries):m_psi(psi),
m_psi2(psi2),
m_siPageType(siPageType),
m_psiObjectInfo(psiObjectInfo),
m_hEntries(hEntries),
m_hPropEntries(hPropEntries),
m_hMergedEntries(NULL),
m_hFont(NULL)
{
TraceEnter(TRACE_ACLBLOAT, "CACLBloat::CACLBloat");
if(m_psi)
m_psi->AddRef();
if(m_psi2)
m_psi2->AddRef();
}
CACLBloat::~CACLBloat()
{
if(m_psi)
m_psi->Release();
if(m_psi2)
m_psi2->Release();
if(m_hMergedEntries)
{
UINT cItems = DPA_GetPtrCount(m_hMergedEntries);
for(UINT iItems = 0; iItems < cItems; ++iItems)
{
delete (PACE)DPA_FastGetPtr(m_hMergedEntries, iItems);
}
DPA_Destroy(m_hMergedEntries);
}
if(m_hFont)
DeleteObject(m_hFont);
}
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::IsAclBloated
//
// Synopsis: ACL is bloated if number of entries which inherits to child objects
// is more than 8
//
//
// History: 04-April 2001 hiteshr Created
//
//---------------------------------------------------------------------------
BOOL
CACLBloat::IsAclBloated()
{
TraceEnter(TRACE_ACLBLOAT, "CACLBloat::IsAclBloated");
if(!m_hMergedEntries)
{
m_hMergedEntries = DPA_Create(4);
if(!m_hMergedEntries)
return FALSE;
}
if(SUCCEEDED(MergeAces(m_hEntries, m_hPropEntries, m_hMergedEntries)))
{
int cItems = DPA_GetPtrCount(m_hMergedEntries);
if(cItems > ACL_BLOAT_LIMIT)
return TRUE;
}
return FALSE;
}
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::DoModalDialog
//
// Synopsis: Creates modal dialogbox
//
// Arguments: [hwndParent] - handle to owner window of dialog to create
//
// Returns: Dialog's return code
//
// History: 04-April-2001 hiteshr Created
//
//---------------------------------------------------------------------------
BOOL
CACLBloat::DoModalDialog(HWND hwndParent)
{
TraceEnter(TRACE_ACLBLOAT, "CACLBloat::CACLBloat");
INT_PTR iResult = DialogBoxParam(::hModule,
MAKEINTRESOURCE(IDD_ACLBLOAT),
hwndParent,
CACLBloat::_DlgProc,
(LPARAM) this);
return static_cast<BOOL>(iResult);
}
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::_DlgProc
//
// Synopsis: Dialog box callback
//
// Returns: Dialog's return code
//
// History: 04-April-2001 hiteshr Created
//
//---------------------------------------------------------------------------
INT_PTR CALLBACK
CACLBloat::_DlgProc(HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
BOOL bReturn = TRUE;
CACLBloat *pThis = (CACLBloat *)GetWindowLongPtr(hDlg, DWLP_USER);
if (!pThis && uMsg != WM_INITDIALOG)
{
return FALSE;
}
switch (uMsg)
{
case WM_INITDIALOG:
pThis = (CACLBloat*) lParam;
ASSERT(pThis);
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR) pThis);
pThis->InitDlg(hDlg);
break;
case WM_COMMAND:
bReturn = pThis->OnCommand(hDlg, wParam, lParam);
break;
case WM_NOTIFY:
bReturn = pThis->OnNotify(hDlg, wParam, lParam);
break;
default:
bReturn = FALSE;
break;
}
return bReturn;
}
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::InitDlg
//
// Synopsis: Initialize the ACL bloat dialog box
//
//
// History: 04-April-2001 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT
CACLBloat::InitDlg( HWND hDlg )
{
TraceEnter(TRACE_ACLBLOAT, "CACLBloat::CACLBloat");
HRESULT hr = S_OK;
HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
//
// Set up the listview control
//
HWND hListView = GetDlgItem( hDlg, IDC_ACEL_BLOAT );
//
// Set extended LV style for whole line selection with InfoTips
//
ListView_SetExtendedListViewStyleEx(hListView,
LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP,
LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
//
// Add appropriate columns
//
RECT rc;
GetClientRect(hListView, &rc);
LV_COLUMN col;
col.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH;
col.fmt = LVCFMT_LEFT;
col.iSubItem = 0;
col.cx = rc.right;
ListView_InsertColumn(hListView, 0, &col);
//
//Add the aces to listview
//
hr = AddAcesFromDPA(hListView, m_hMergedEntries);
if(FAILED(hr))
return hr;
//
//Add a warning icon
//
// add the warning icon
HICON hWarn = LoadIcon(NULL, IDI_WARNING);
SendDlgItemMessage(hDlg, // dialog box window handle
IDC_BLOAT_WARN_ICON, // icon identifier
STM_SETIMAGE, // message to send
(WPARAM) IMAGE_ICON, // image type
(LPARAM) hWarn); // icon handle
//
//Set the title of dialog box
//
LPTSTR pszCaption = NULL;
if(FormatStringID(&pszCaption,
::hModule,
m_siPageType == SI_PAGE_AUDIT ? IDS_ACEE_AUDIT_TITLE : IDS_ACEE_PERM_TITLE,
m_psiObjectInfo->pszObjectName))
{
SetWindowText(hDlg, pszCaption);
LocalFreeString(&pszCaption);
}
//
//Set the warning message
//
UINT cItem = DPA_GetPtrCount(m_hMergedEntries);
WCHAR buffer[34];
_itow(cItem,buffer,10);
if(FormatStringID(&pszCaption,
::hModule,
m_siPageType == SI_PAGE_AUDIT ? IDS_BLOAT_AUDIT_WARN : IDS_BLOAT_PERM_WARN,
buffer))
{
SetDlgItemText(hDlg, IDC_BLOAT_LV_STATIC, pszCaption);
LocalFreeString(&pszCaption);
}
//
//Set the line 1
//
WCHAR szBuffer[1024];
if(LoadString(::hModule,
m_siPageType == SI_PAGE_AUDIT ? IDS_BLOAT_AUDIT_LINE1: IDS_BLOAT_PERM_LINE1,
szBuffer,
1024))
SetDlgItemText(hDlg,IDC_BLOAT_LINE1_STATIC, szBuffer);
//
//Set the line 2
//
if(LoadString(::hModule,
m_siPageType == SI_PAGE_AUDIT ? IDS_BLOAT_AUDIT_LINE2: IDS_BLOAT_PERM_LINE2,
szBuffer,
1024))
SetDlgItemText(hDlg,IDC_BLOAT_LINE2_STATIC, szBuffer);
//
//make warning bold
//
MakeBold(GetDlgItem(hDlg,IDC_ACLB_WARNING), &m_hFont);
SetCursor(hcur);
return hr;
}
BOOL
CACLBloat::OnNotify(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
LPNMHDR pnmh = (LPNMHDR)lParam;
LPNM_LISTVIEW pnmlv = (LPNM_LISTVIEW)lParam;
// Set default return value
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
switch (pnmh->code)
{
#define lvi (((NMLVDISPINFO*)lParam)->item)
case LVN_GETDISPINFO:
{
PACE pAce = (PACE)lvi.lParam;
if ((lvi.mask & LVIF_TEXT) && pAce)
{
if (0 == lvi.iSubItem)
{
lvi.pszText = pAce->GetAccessType();
}
}
}
break;
#undef lvi
}
return TRUE;
}
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::MergeAces
//
// Synopsis: Merges the aces from Object and Property Pages in to single
// List
//
//
// History: 04-April-2001 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT
CACLBloat::MergeAces(HDPA hEntries, HDPA hPropEntries, HDPA hMergedList)
{
if(!hMergedList || (!hEntries && !hPropEntries))
return E_POINTER;
HRESULT hr = S_OK;
if(hEntries)
{
UINT cItems = DPA_GetPtrCount(hEntries);
for(UINT iItems = 0; iItems < cItems; ++iItems)
{
hr = AddAce(hMergedList,
(PACE_HEADER)DPA_FastGetPtr(hEntries, iItems));
if(FAILED(hr))
return hr;
}
}
if(hPropEntries)
{
UINT cItems = DPA_GetPtrCount(hPropEntries);
for(UINT iItems = 0; iItems < cItems; ++iItems)
{
hr = AddAce(hMergedList,
(PACE_HEADER)DPA_FastGetPtr(hPropEntries, iItems));
if(FAILED(hr))
return hr;
}
}
return S_OK;
}
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::AddAce
//
// Synopsis: Converts AceHeader to ACLUI Ace structure
//
//
// History: 04-April-2001 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT
CACLBloat::AddAce(HDPA hEntries,
PACE_HEADER pAceHeader)
{
//
//This Ace doesn't propogate to child objects,
//so we don't show this.
//
if(!(pAceHeader->AceFlags & CONTAINER_INHERIT_ACE))
return S_OK;
PACE pAce = new CAce(pAceHeader);
if (pAce)
{
return AddAce(hEntries, pAce);
}
else
return E_OUTOFMEMORY;
}
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::AddAce
//
// Synopsis: Add an Ace to list. First it tries to merge it with existing
// aces in the list.
//
//
// History: 04-April-2001 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT
CACLBloat::AddAce(HDPA hEntries,
PACE pAceNew)
{
TraceEnter(TRACE_ACLBLOAT, "CACLBloat::AddAce");
TraceAssert(hEntries != NULL);
TraceAssert(pAceNew != NULL);
if (pAceNew == NULL)
return E_POINTER;
m_psi->MapGeneric(&pAceNew->ObjectType, &pAceNew->AceFlags, &pAceNew->Mask);
//
// Try to merge the new ACE with an existing entry in the list.
//
int cItems = DPA_GetPtrCount(hEntries);
for( int iItems = 0; iItems < cItems; ++iItems)
{
PACE pAceCompare = (PACE)DPA_FastGetPtr(hEntries, iItems);
if (pAceCompare != NULL)
{
switch (pAceNew->Merge(pAceCompare))
{
case MERGE_MODIFIED_FLAGS:
case MERGE_MODIFIED_MASK:
// The ACEs were merged into pAceNew.
case MERGE_OK_1:
//
// The new ACE implies the existing ACE, so the existing
// ACE can be removed.
//
// First copy the name so we don't have to look
// it up again. (Don't copy the other strings
// since they may be different.)
//
// Then keep looking. Maybe we can remove some more entries
// before adding the new one.
//
DPA_DeletePtr(hEntries, iItems);
delete pAceCompare;
--cItems;
--iItems;
break;
case MERGE_OK_2:
//
// The existing ACE implies the new ACE, so we don't
// need to do anything here.
//
delete pAceNew;
return S_OK;
break;
}
}
}
DPA_AppendPtr(hEntries, pAceNew);
return S_OK;
}
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::GetItemString
//
// Synopsis: Gets a display name for the item.
//
//
// History: 04-April-2001 hiteshr Created
//
//---------------------------------------------------------------------------
LPCTSTR
CACLBloat::GetItemString(LPCTSTR pszItem,
LPTSTR pszBuffer,
UINT ccBuffer)
{
TraceEnter(TRACE_ACELIST, "CACLBloat::GetItemString");
if (pszItem == NULL)
{
LoadString(::hModule, IDS_SPECIAL, pszBuffer, ccBuffer);
pszItem = pszBuffer;
}
else if (IS_INTRESOURCE(pszItem))
{
if (LoadString(m_psiObjectInfo->hInstance,
(UINT)((ULONG_PTR)pszItem),
pszBuffer,
ccBuffer) == 0)
{
LoadString(::hModule, IDS_SPECIAL, pszBuffer, ccBuffer);
}
pszItem = pszBuffer;
}
TraceLeaveValue(pszItem);
}
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::TranslateAceIntoRights
//
// Synopsis: Converts Aces Mask in to a string taking into account
// the Object Guid.
//
//
// History: 04-April-2001 hiteshr Created
//
//---------------------------------------------------------------------------
LPCTSTR
CACLBloat::TranslateAceIntoRights(DWORD dwMask,
const GUID *pObjectType,
PSI_ACCESS pAccess,
ULONG cAccess)
{
TraceEnter(TRACE_ACELIST, "CACLBloat::TranslateAceIntoRights");
TraceAssert(pObjectType != NULL);
if(!pAccess || !cAccess)
return NULL;
LPCTSTR pszName = NULL;
if (pAccess && cAccess)
{
//
// Look for a name for the mask
//
for (UINT iItem = 0; iItem < cAccess; iItem++)
{
if ( dwMask == pAccess[iItem].mask &&
IsSameGUID(pObjectType, pAccess[iItem].pguid) )
{
pszName = pAccess[iItem].pszName;
break;
}
}
}
TraceLeaveValue(pszName);
}
//+--------------------------------------------------------------------------
//
// Member: CACLBloat::AddAcesFromDPA
//
// Synopsis: Add ace from list to ListView control.
//
//
// History: 04-April-2001 hiteshr Created
//
//---------------------------------------------------------------------------
HRESULT
CACLBloat::AddAcesFromDPA(HWND hListView, HDPA hEntries)
{
ULONG iDefaultAccess = 0;
PSI_ACCESS pAccess = NULL;
ULONG cAccess = 0;
HRESULT hr = S_OK;
if(!hEntries)
return E_POINTER;
//
//Get the count of items
//
int cItems = DPA_GetPtrCount(hEntries);
GUID* pGUID = NULL;
PACE pAce = (PACE)DPA_FastGetPtr(hEntries, 0);
if(pAce)
{
//
//Get the AccessRight array for the guid
//
hr = m_psi->GetAccessRights(&pAce->InheritedObjectType,
SI_ADVANCED|SI_EDIT_EFFECTIVE,
&pAccess,
&cAccess,
&iDefaultAccess);
if(FAILED(hr))
return hr;
pGUID = &pAce->InheritedObjectType;
}
for( int iItem = 0; iItem < cItems; ++iItem)
{
pAce = (PACE)DPA_FastGetPtr(hEntries, iItem);
if(pAce)
{
if(!IsSameGUID(pGUID, &pAce->InheritedObjectType))
{
//
//if Guid is not same as one for which we have access right info,
//fetch access right info for new guid
//
hr = m_psi->GetAccessRights(&pAce->InheritedObjectType,
SI_ADVANCED | SI_EDIT_EFFECTIVE,
&pAccess,
&cAccess,
&iDefaultAccess);
if(FAILED(hr))
return hr;
pGUID = &pAce->InheritedObjectType;
}
TCHAR szBuffer[MAX_COLUMN_CHARS];
LPCTSTR pszRights = NULL;
pszRights = TranslateAceIntoRights(pAce->Mask,
&pAce->ObjectType,
pAccess,
cAccess);
//
// If this is a property ACE, give it a name like "Read property" or
// "Write property". Also, remember that it's a property ACE so we
// can show the Property page first when editing this ACE.
//
// This is a bit slimy, since it assumes DS property access bits are
// the only ones that will ever be used on the properties page.
//
if ((m_psiObjectInfo->dwFlags & SI_EDIT_PROPERTIES) &&
(pAce->Flags & ACE_OBJECT_TYPE_PRESENT) &&
(pAce->Mask & (ACTRL_DS_READ_PROP | ACTRL_DS_WRITE_PROP)) &&
!(pAce->Mask & ~(ACTRL_DS_READ_PROP | ACTRL_DS_WRITE_PROP)))
{
pAce->SetPropertyAce(TRUE);
if (pszRights == NULL)
{
UINT idString = 0;
switch (pAce->Mask & (ACTRL_DS_READ_PROP | ACTRL_DS_WRITE_PROP))
{
case ACTRL_DS_READ_PROP:
idString = IDS_READ_PROP;
break;
case ACTRL_DS_WRITE_PROP:
idString = IDS_WRITE_PROP;
break;
case (ACTRL_DS_READ_PROP | ACTRL_DS_WRITE_PROP):
idString = IDS_READ_WRITE_PROP;
break;
}
if (idString)
{
LoadString(::hModule, idString, szBuffer, ARRAYSIZE(szBuffer));
pszRights = szBuffer;
}
}
}
pszRights = GetItemString(pszRights, szBuffer, ARRAYSIZE(szBuffer));
pAce->SetAccessType(pszRights);
LV_ITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
lvi.state = 0;
lvi.stateMask = LVIS_CUT;
lvi.iItem = iItem;
lvi.iSubItem = 0;
lvi.pszText = LPSTR_TEXTCALLBACK;
lvi.lParam = (LPARAM)pAce;
//
// insert the item into the list
//
iItem = ListView_InsertItem(hListView, &lvi);
if (iItem == -1)
delete pAce;
}
}
return hr;
}
BOOL
CACLBloat::OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
BOOL fHandled = TRUE;
switch (LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, FALSE);
break;
case IDCANCEL:
EndDialog(hDlg, TRUE);
break;
case IDHELP:
HtmlHelp(NULL,
L"aclui.chm::/ACLUI_acl_BP.htm",
HH_DISPLAY_TOPIC,
0);
break;
default:
fHandled = FALSE;
break;
}
return fHandled;
}