//+------------------------------------------------------------------------- // // 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(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; }