Entry Type |
Principal/Group |
What Rights? |
- |
Bob |
rw |
+ |
Friends |
rw |
Figure 4 SI_ACCESS and ISecurityInformation
//////////////////////////////////////////////////////////////////////////////
// annotated excerpt from ACLUI.H
//
typedef struct _SI_ACCESS
{
const GUID *pguid; // GUID_NULL, or property identifier
ACCESS_MASK mask; // may contain one or more permissions
LPCWSTR pszName; // may be resource ID (MAKEINTRESOURCE)
DWORD dwFlags;
} SI_ACCESS, *PSI_ACCESS;
// ISecurityInformation wasn't even defined in IDL, tsk, tsk...
// so the following interface was reverse-engineered by Keith Brown
// for readability
interface ISecurityInformation : IUnknown
{
// *** ISecurityInformation methods ***
HRESULT GetObjectInformation( [in, out] PSI_OBJECT_INFO pObjectInfo );
HRESULT GetSecurity( [in] SECURITY_INFORMATION RequestedInformation,
[out] PSECURITY_DESCRIPTOR* ppSecurityDescriptor,
[in] BOOL fDefault );
HRESULT SetSecurity( [in] SECURITY_INFORMATION SecurityInformation,
[out] PSECURITY_DESCRIPTOR pSecurityDescriptor );
HRESULT GetAccessRights( [in] const GUID* pguidObjectType,
[in] DWORD dwFlags,
[out] PSI_ACCESS* ppAccess,
[out] ULONG* pcAccesses,
[out] ULONG* piDefaultAccess );
HRESULT MapGeneric( const GUID* pguidObjectType,
UCHAR* pAceFlags,
ACCESS_MASK* pMask);
HRESULT GetInheritTypes( PSI_INHERIT_TYPE* ppInheritTypes,
ULONG* pcInheritTypes );
HRESULT PropertySheetPageCallback( HWND hwnd,
UINT uMsg,
SI_PAGE_TYPE uPage );
};
HPROPSHEETPAGE WINAPI CreateSecurityPage( ISecurityInfo* psi );
BOOL WINAPI EditSecurity( HWND hwndOwner, ISecurityInfo* psi );
Figure 5 ISecurityInformation Implementation
//////////////////////////////////////////////////////////////////////////////
//
// excerpt from winstadacl.cpp
//
STDMETHODIMP
CWindowObjectSecurityInfoBase::
GetObjectInformation( SI_OBJECT_INFO* poi )
{
// We want to edit the DACL (PERMS), the OWNER,
// and we want the Advanced button
poi->dwFlags = SI_EDIT_OWNER | SI_EDIT_PERMS |
SI_ADVANCED | m_grfExtraFlags;
// this determines the module used to discover stringtable entries
poi->hInstance = g_hInst;
poi->pszServerName = L"";
poi->pszObjectName = const_cast<wchar_t*>( m_pszObjectName );
poi->pszPageTitle = const_cast<wchar_t*>( m_pszPageTitle );
if ( m_pszPageTitle )
poi->dwFlags |= SI_PAGE_TITLE;
return S_OK;
}
STDMETHODIMP
CWindowObjectSecurityInfoBase::
GetSecurity( SECURITY_INFORMATION ri, void** ppsd, BOOL bDefault )
{
// map directly onto the winsta/desktop security descriptor
const DWORD err = GetSecurityInfo( m_handle, SE_WINDOW_OBJECT, ri,
0, 0, 0, 0, ppsd );
return err ? HRESULT_FROM_WIN32(err) : S_OK;
}
STDMETHODIMP
CWindowObjectSecurityInfoBase::
SetSecurity( SECURITY_INFORMATION ri, void* psd )
{
// map directly onto the winsta/desktop security descriptor
void* pOwner = 0;
void* pGroup = 0;
ACL* pdacl = 0;
ACL* psacl = 0;
BOOL bDefaulted;
BOOL bPresent;
if ( OWNER_SECURITY_INFORMATION & ri )
GetSecurityDescriptorOwner( psd, &pOwner, &bDefaulted );
if ( GROUP_SECURITY_INFORMATION & ri )
GetSecurityDescriptorGroup( psd, &pGroup, &bDefaulted );
if ( DACL_SECURITY_INFORMATION & ri )
GetSecurityDescriptorDacl( psd, &bPresent, &pdacl, &bDefaulted );
if ( SACL_SECURITY_INFORMATION & ri )
GetSecurityDescriptorSacl( psd, &bPresent, &psacl, &bDefaulted );
const DWORD err = SetSecurityInfo( m_handle, SE_WINDOW_OBJECT, ri,
pOwner, pGroup, pdacl, psacl );
return err ? HRESULT_FROM_WIN32(err) : S_OK;
}
STDMETHODIMP
CWinstaSecurityInfo::
PropertySheetPageCallback( HWND hwnd, UINT msg, SI_PAGE_TYPE pt )
{
// this is effectively a pass-through from the PropertySheet callback,
// which we don't care about for this sample
return S_OK;
}
STDMETHODIMP
CWinstaSecurityInfo::
GetAccessRights( const GUID*, DWORD dwFlags,
SI_ACCESS** ppAccess,
ULONG* pcAccesses,
ULONG* piDefaultAccess )
{
// here's where we hand back the winsta permissions->strings mapping
*ppAccess = const_cast<SI_ACCESS*>( g_winstaAccess );
*pcAccesses = sizeof g_winstaAccess / sizeof *g_winstaAccess;
*piDefaultAccess = 0;
return S_OK;
}
STDMETHODIMP
CWinstaSecurityInfo::
MapGeneric( const GUID*, UCHAR* pAceFlags, ACCESS_MASK* pMask )
{
// here's where we hand back the winsta generic permissions mapping
MapGenericMask( pMask,
const_cast<GENERIC_MAPPING*>( &g_winstaGenericMapping ) );
return S_OK;
}
STDMETHODIMP
CWinstaSecurityInfo::
GetInheritTypes( SI_INHERIT_TYPE** ppInheritTypes,
ULONG* pcInheritTypes )
{
// here's where we hand back the winsta inheritance combinations
// and string mappings
*ppInheritTypes = g_winstaInheritTypes;
*pcInheritTypes = sizeof g_winstaInheritTypes /
sizeof *g_winstaInheritTypes;
return S_OK;
}
STDMETHODIMP
CDesktopSecurityInfo::
GetAccessRights( const GUID*, DWORD dwFlags, SI_ACCESS** ppAccess,
ULONG* pcAccesses, ULONG* piDefaultAccess )
{
// here's where we hand back the desktop permissions->strings mapping
*ppAccess = const_cast<SI_ACCESS*>( g_desktopAccess );
*pcAccesses = sizeof g_desktopAccess / sizeof *g_desktopAccess;
*piDefaultAccess = 0;
return S_OK;
}
STDMETHODIMP
CDesktopSecurityInfo::
MapGeneric( const GUID*, UCHAR* pAceFlags, ACCESS_MASK* pMask )
{
// here's where we hand back the desktop generic permissions mapping
MapGenericMask( pMask,
const_cast<GENERIC_MAPPING*>( &g_desktopGenericMapping ) );
return S_OK;
}
STDMETHODIMP
CDesktopSecurityInfo::
GetInheritTypes( SI_INHERIT_TYPE** ppInheritTypes, ULONG* pcInheritTypes )
{
// Desktops are not containers, and thus have no options for inheritable
// entries in the DACL or SACL. Since we didn't specify SI_CONTAINER in
// our GetObjectInformation call, this function will never be called.
return E_NOTIMPL;
}
Figure 6 Creating a Property Sheet
//////////////////////////////////////////////////////////////////////////////
//
// excerpt from winstadacl.cpp
//
HWINSTA hwinsta = GetProcessWindowStation();
HDESK hdesk = GetThreadDesktop( GetCurrentThreadId() );
HPROPSHEETPAGE rghps[2];
{
// here's where I create a couple of implementations of
// ISecurityInformation
CWinstaSecurityInfo* pwsi = new CWinstaSecurityInfo(
hwinsta,
L"Interactive Window Station",
L"Window Station" );
CDesktopSecurityInfo* pdsi = new CDesktopSecurityInfo(
hdesk,
L"Default Desktop",
L"Desktop" );
pwsi->AddRef();
pdsi->AddRef();
// convert them into property pages...
rghps[0] = CreateSecurityPage( pwsi );
rghps[1] = CreateSecurityPage( pdsi );
pdsi->Release();
pwsi->Release();
}
// this is just basic common control goo (setting up a property sheet)
PROPSHEETHEADER psh; ZeroMemory( &psh, sizeof psh );
psh.dwSize = sizeof psh;
psh.hInstance = g_hInst;
psh.pszCaption = L"Window Station and Desktop Security Editor";
psh.nPages = sizeof rghps / sizeof *rghps;
psh.phpage = rghps;
// display the property sheet
PropertySheet( &psh );