Figure 1   Anatomy of a DACL

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 );