windows-nt/Source/XPSP1/NT/shell/osshell/security/aclui/effperm.cpp

550 lines
14 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: owner.cpp
//
// This file contains the implementation of the Owner page.
//
//--------------------------------------------------------------------------
#include "aclpriv.h"
#include <initguid.h> // needed to get the GUIDs defined in oleacc.h
#include <oleacc.h> // contains IAccProp* definitions
//Context Help IDs
const static DWORD aEffHelpIDs[] =
{
IDC_EFF_NAME_STATIC, IDH_EFF_NAME,
IDC_EFF_NAME, IDH_EFF_NAME,
IDC_EFF_SELECT, IDH_EFF_SELECT,
IDC_EFF_PERMISSION_STATIC, IDH_EFF_PERM_LIST,
IDC_EFF_PERM_LIST, IDH_EFF_PERM_LIST,
IDC_EFF_STATIC, -1,
0, 0
};
LPCWSTR g_ListStateMap =
L"A:0"
L":0:0x50" // checked, disabled - STATE_SYSTEM_READONLY | STATE_SYSTEM_CHECKED
L":1:0x40" // disabled - STATE_SYSTEM_READONLY
L":";
LPCWSTR g_ListRoleMap =
L"A:0"
L":0:0x2C" // checkbox - ROLE_SYSTEM_CHECKBUTTON (ie. checkbox)
L":1:0x2C"
L":";
int LV_ADDITEM(HWND hwndList,
LPCTSTR pszName,
int index,
PSI_ACCESS pAccess,
BOOL bChecked)
{
LVITEM lvItem;
TraceAssert(pAccess != NULL);
TraceAssert(pszName != NULL);
lvItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
lvItem.iItem = index;
lvItem.iSubItem = 0;
lvItem.pszText = (LPTSTR)pszName;
lvItem.lParam = (LPARAM)pAccess;
lvItem.iImage = bChecked ? 0 : 1;
// Insert item into list
index = ListView_InsertItem(hwndList, &lvItem);
ListView_SetCheckState(hwndList,index,bChecked);
return index;
}
typedef struct _EffCacheItem
{
POBJECT_TYPE_LIST pObjectTypeList;
ULONG cObjectTypeListLength;
PACCESS_MASK pGrantedAccessList;
PSID pSid;
}EFFCACHEITEM,*PEFFCACHEITEM;
//This Function checks is pAccess is granted.
BOOL IsChecked( PSI_ACCESS pAccess,
PEFFCACHEITEM pCacheItem)
{
TraceEnter(TRACE_EFFPERM, "IsChecked");
TraceAssert(pCacheItem != NULL);
TraceAssert(pAccess != NULL);
POBJECT_TYPE_LIST pObjectTypeList = pCacheItem->pObjectTypeList;
ULONG cObjectTypeListLength = pCacheItem->cObjectTypeListLength;
PACCESS_MASK pGrantedAccessList = pCacheItem->pGrantedAccessList;
//0th Grant is for full object.
if( (pAccess->mask & pGrantedAccessList[0]) == pAccess->mask )
return TRUE;
BOOL bGuidNULL = pAccess->pguid ?IsEqualGUID(*(pAccess->pguid), GUID_NULL): TRUE;
LPGUID pguid;
for( UINT i = 1; i < cObjectTypeListLength; ++i )
{
pguid = pObjectTypeList[i].ObjectType;
if( pguid == NULL ||
IsEqualGUID(*pguid, GUID_NULL) ||
(!bGuidNULL && IsEqualGUID(*pguid,*(pAccess->pguid))) )
{
if( (pAccess->mask & pGrantedAccessList[i]) == pAccess->mask )
return TRUE;
}
}
return FALSE;
}
class CEffPage: public CSecurityPage
{
public:
CEffPage(LPSECURITYINFO psi, SI_OBJECT_INFO *psiObjectInfo);
virtual ~CEffPage();
private:
virtual BOOL DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL InitDlg(HWND hDlg);
void OnSelect(HWND hDlg);
void InitListBox(HWND hDlg);
HRESULT GetEffectivePerm(PSID pSid, PEFFCACHEITEM *ppCacheItem);
PSID GetSelectedSID(){ return m_pSid; }
private:
PSID m_pSid; //Sid of the security principal for which permissions are displayed
PSI_ACCESS m_pAccess;
ULONG m_cAccesses;
};
HPROPSHEETPAGE
CreateEffectivePermPage(LPSECURITYINFO psi, SI_OBJECT_INFO *psiObjectInfo)
{
HPROPSHEETPAGE hPage = NULL;
CEffPage *pPage;
TraceEnter(TRACE_EFFPERM, "CreateEffectivePermPage");
TraceAssert(psi!=NULL);
TraceAssert(psiObjectInfo);
pPage = new CEffPage(psi, psiObjectInfo);
if (pPage)
{
hPage = pPage->CreatePropSheetPage(MAKEINTRESOURCE(IDD_EFFECTIVE_PERM_PAGE));
if (!hPage)
delete pPage;
}
TraceLeaveValue(hPage);
}
CEffPage::CEffPage(LPSECURITYINFO psi, SI_OBJECT_INFO *psiObjectInfo)
: CSecurityPage(psi, SI_PAGE_OWNER) , m_pSid(NULL),
m_pAccess(NULL), m_cAccesses(0)
{
// Lookup known SIDs asynchronously so the dialog
// will initialize faster
}
CEffPage::~CEffPage()
{
if (m_pSid)
LocalFree(m_pSid);
}
BOOL
CEffPage::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BOOL bResult = TRUE;
LPPSHNOTIFY lpsn;
switch(uMsg)
{
case WM_INITDIALOG:
InitDlg(hDlg);
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_EFF_SELECT:
OnSelect(hDlg);
break;
default:
bResult = FALSE;
}
break;
case WM_HELP:
if (IsWindowEnabled(hDlg))
{
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
c_szAcluiHelpFile,
HELP_WM_HELP,
(DWORD_PTR)aEffHelpIDs);
}
break;
case WM_CONTEXTMENU:
if (IsWindowEnabled(hDlg))
{
WinHelp(hDlg,
c_szAcluiHelpFile,
HELP_CONTEXTMENU,
(DWORD_PTR)aEffHelpIDs);
}
break;
case PSM_QUERYSIBLINGS:
if(GetSelectedSID())
InitListBox(hDlg);
break;
default:
bResult = FALSE;
}
return bResult;
}
BOOL
CEffPage::InitDlg( HWND hDlg )
{
HWND hwndList;
RECT rc;
LV_COLUMN col;
TCHAR szBuffer[MAX_COLUMN_CHARS];
HRESULT hr = S_OK;
ULONG iDefaultAccess;
HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
TraceEnter(TRACE_EFFPERM, "CEffPage::InitDlg");
TraceAssert(hDlg != NULL);
TraceAssert(m_psi != NULL);
TraceAssert(m_pei != NULL);
hwndList = GetDlgItem(hDlg, IDC_EFF_PERM_LIST);
//
// Create & set the image list for the listview. If there is a
// problem CreateSidImageList will return NULL which won't hurt
// anything. In that case we'll just continue without an image list.
//
ListView_SetImageList(hwndList,
LoadImageList(::hModule, MAKEINTRESOURCE(IDB_CHECKBOX)),
LVSIL_SMALL);
// Set extended LV style for whole line selection with InfoTips
ListView_SetExtendedListViewStyleEx(hwndList,
LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP,
LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
IAccPropServices * pAccPropSvc = NULL;
hr = CoCreateInstance( CLSID_AccPropServices, NULL, CLSCTX_SERVER, IID_IAccPropServices, (void **) & pAccPropSvc );
if( hr == S_OK && pAccPropSvc )
{
// Don't have to check HRESULT here, since if they fail we just ignore anyway,
// but may want to log it while debugging.
pAccPropSvc->SetHwndPropStr(hwndList, OBJID_CLIENT, 0, PROPID_ACC_ROLEMAP, g_ListRoleMap );
pAccPropSvc->SetHwndPropStr(hwndList, OBJID_CLIENT, 0, PROPID_ACC_STATEMAP, g_ListStateMap );
pAccPropSvc->Release();
}
//
// Add appropriate listview columns
//
GetClientRect(hwndList, &rc);
LoadString(::hModule, IDS_PERMISSIONS, szBuffer, ARRAYSIZE(szBuffer));
col.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
col.fmt = LVCFMT_LEFT;
col.pszText = szBuffer;
col.iSubItem = 0;
col.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
ListView_InsertColumn(hwndList, 0, &col);
//Get the access Rights
hr = m_psi->GetAccessRights(&GUID_NULL,
SI_ADVANCED|SI_EDIT_EFFECTIVE,
&m_pAccess,
&m_cAccesses,
&iDefaultAccess);
FailGracefully(hr, "GetAccessRights Failed");
//Initialize the List box
InitListBox(hDlg);
exit_gracefully:
SetCursor(hcur);
if (FAILED(hr))
{
HWND hwnd;
// Hide and disable everything
for (hwnd = GetWindow(hDlg, GW_CHILD);
hwnd != NULL;
hwnd = GetWindow(hwnd, GW_HWNDNEXT))
{
ShowWindow(hwnd, SW_HIDE);
EnableWindow(hwnd, FALSE);
}
// Enable and show the "No Security" message
hwnd = GetDlgItem(hDlg, IDC_NO_EFFECTIVE);
EnableWindow(hwnd, TRUE);
ShowWindow(hwnd, SW_SHOW);
}
TraceLeaveValue(TRUE);
}
VOID
CEffPage::OnSelect(HWND hDlg)
{
PUSER_LIST pUserList = NULL;
LPEFFECTIVEPERMISSION pei;
HRESULT hr = S_OK;
TraceEnter(TRACE_EFFPERM, "CEffPage::OnSelect");
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_EFF_NAME, pUserList->rgUsers[0].pszName);
}
LocalFree(pUserList);
InitListBox(hDlg);
}
}
VOID
CEffPage::InitListBox(HWND hDlg)
{
HWND hwndList;
BOOL bProperties;
PSI_ACCESS pAccess;
ULONG cAccesses;
DWORD dwType;
TCHAR szName[MAX_PATH];
PSID pSid = NULL;
PEFFCACHEITEM pCacheItem = NULL;
int index;
TraceEnter(TRACE_EFFPERM, "CEffPage::InitListBox");
TraceAssert( m_pAccess != NULL );
TraceAssert(m_cAccesses != 0 );
HRESULT hr = S_OK;
hwndList = GetDlgItem(hDlg, IDC_EFF_PERM_LIST);
if(!IsWindowEnabled(hwndList))
{
//Hide Error Message
HWND hwnd = GetDlgItem(hDlg, IDC_EFF_ERROR);
EnableWindow(hwnd, FALSE);
ShowWindow(hwnd, SW_HIDE);
//Show List box
EnableWindow(hwndList, TRUE);
ShowWindow(hwndList, SW_SHOW);
}
//Clear all items
ListView_DeleteAllItems(hwndList);
pAccess = m_pAccess;
cAccesses = m_cAccesses;
dwType = SI_ACCESS_SPECIFIC | SI_ACCESS_PROPERTY;
//Get the current sid
pSid = GetSelectedSID();
if( pSid )
{
hr = GetEffectivePerm(pSid, &pCacheItem);
FailGracefully(hr,"GetEffectivePermission Failed");
}
index = 0;
// Enumerate the permissions and add to the checklist
ULONG i;
for (i = 0; i < cAccesses; i++, pAccess++)
{
LPCTSTR pszName;
// Only add permissions that have any of the flags specified in dwType
if (!(pAccess->dwFlags & dwType))
continue;
//Don't Add Permission which have inherit only on
if( pAccess->dwFlags & INHERIT_ONLY_ACE )
continue;
pszName = pAccess->pszName;
if (IS_INTRESOURCE(pszName))
{
TraceAssert(m_siObjectInfo.hInstance != NULL);
if (LoadString(m_siObjectInfo.hInstance,
(UINT)((ULONG_PTR)pszName),
szName,
ARRAYSIZE(szName)) == 0)
{
LoadString(::hModule,
IDS_UNKNOWN,
szName,
ARRAYSIZE(szName));
}
pszName = szName;
}
BOOL bChecked = FALSE;
if(pSid)
{
bChecked = IsChecked( pAccess, pCacheItem );
}
index = LV_ADDITEM( hwndList, pszName, index, pAccess, bChecked);
index++;
}
if(index)
{
SelectListViewItem(hwndList, 0);
// Redraw the list
SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
ListView_RedrawItems(hwndList, 0, -1);
}
exit_gracefully:
if(pCacheItem)
{
if(pCacheItem->pGrantedAccessList)
LocalFree(pCacheItem->pGrantedAccessList);
LocalFree(pCacheItem);
}
if(FAILED(hr))
{
//Hide List box
HWND hwnd = GetDlgItem(hDlg, IDC_EFF_PERM_LIST);
EnableWindow(hwnd, FALSE);
ShowWindow(hwnd, SW_HIDE);
//Format Error Message To Display
WCHAR buffer[MAX_PATH];
LPWSTR pszCaption = NULL;
GetWindowText(GetDlgItem(hDlg, IDC_EFF_NAME),
buffer,
MAX_PATH-1);
FormatStringID(&pszCaption, ::hModule, IDS_EFF_ERROR, buffer);
//Show Error Message
hwnd = GetDlgItem(hDlg, IDC_EFF_ERROR);
EnableWindow(hwnd, TRUE);
SetWindowText(hwnd,pszCaption);
ShowWindow(hwnd, SW_SHOW);
LocalFreeString(&pszCaption);
}
TraceLeaveVoid();
}
//Calling function frees *ppCacheItem->pGrantedAccessList
//and *ppCacheItem
HRESULT
CEffPage::GetEffectivePerm(PSID pSid,
PEFFCACHEITEM *ppCacheItem )
{
PSECURITY_DESCRIPTOR pSD;
HRESULT hr = S_OK;
ULONG cItems = 0;
PEFFCACHEITEM pCacheTemp = NULL;
TraceEnter(TRACE_EFFPERM, "CEffPage::GetEffectivePerm");
TraceAssert(pSid != NULL);
TraceAssert(ppCacheItem != NULL);
pCacheTemp = (PEFFCACHEITEM)LocalAlloc( LPTR, sizeof(EFFCACHEITEM) + GetLengthSid(pSid));
if(!pCacheTemp)
ExitGracefully(hr, E_OUTOFMEMORY, "Lcoal Alloc Failed");
pCacheTemp->pSid = (PSID)(pCacheTemp + 1);
CopySid(GetLengthSid(pSid), pCacheTemp->pSid, pSid);
if(m_psi)
{
hr = m_psi->GetSecurity(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
&pSD,
FALSE);
FailGracefully(hr, "GetSecurity Failed");
}
if( m_pei)
{
DWORD dwTemp;
hr = m_pei->GetEffectivePermission(&(m_siObjectInfo.guidObjectType),
pCacheTemp->pSid,
m_siObjectInfo.pszServerName,
//NULL,
pSD,
&(pCacheTemp->pObjectTypeList),
&(pCacheTemp->cObjectTypeListLength),
&(pCacheTemp->pGrantedAccessList),
&dwTemp);
if(SUCCEEDED(hr))
{
if(!pCacheTemp->pObjectTypeList || !pCacheTemp->pGrantedAccessList)
hr = E_FAIL;
}
FailGracefully(hr, "GetEffectivePermission Failed");
}
exit_gracefully:
if( !SUCCEEDED(hr) )
{
LocalFree(pCacheTemp);
pCacheTemp = NULL;
}
*ppCacheItem = pCacheTemp;
TraceLeaveResult(hr);
}