/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

    ctaccess.c

Abstract:

    Common access validation test routines

    These routines are used in both kernel and user mode tests.

    This test assumes the security runtime library routines are
    functioning correctly.


Author:

    Robert Reichel      (robertre)      12/14/90

Environment:

    Test of access validation routines

Revision History:

    v1: robertre
        Created

--*/

#include "tsecomm.c"    // Mode dependent macros and routines.



//
//  Define the local macros and procedure for this module
//

//
//  Return a pointer to the first Ace in an Acl (even if the Acl is empty).
//
//      PACE_HEADER
//      FirstAce (
//          IN PACL Acl
//          );
//

#define FirstAce(Acl) ((PVOID)((PUCHAR)(Acl) + sizeof(ACL)))

//
//  Return a pointer to the next Ace in a sequence (even if the input
//  Ace is the one in the sequence).
//
//      PACE_HEADER
//      NextAce (
//          IN PACE_HEADER Ace
//          );
//

#define NextAce(Ace) ((PVOID)((PUCHAR)(Ace) + ((PACE_HEADER)(Ace))->AceSize))

VOID
DumpAcl (
    IN PACL Acl
    );

////////////////////////////////////////////////////////////////
//                                                            //
// Module wide variables                                      //
//                                                            //
////////////////////////////////////////////////////////////////

#define DEFAULT_DACL_LENGTH (1024L)
#define GROUP_IDS_LENGTH (1024L)
#define NEW_GROUP_STATE_LENGTH (1024L)
#define PRIVILEGES_LENGTH (128L)
#define TOO_BIG_ACL_SIZE (2048L)

//
// definitions related to TokenWithGroups
//

#define FLINTSTONE_INDEX  (0L)
#define CHILD_INDEX       (1L)
#define NEANDERTHOL_INDEX (2L)
#define WORLD_INDEX       (3L)
#define GROUP_COUNT       (4L)


//
// Definitions related to TokenWithPrivileges
//

#define UNSOLICITED_INDEX  (0L)
#define SECURITY_INDEX     (1L)
#define PRIVILEGE_COUNT    (2L)

//
//    Access types
//

#define SET_WIDGET_COLOR        0x00000001
#define SET_WIDGET_SIZE         0x00000002
#define GET_WIDGET_COLOR        0x00000004
#define GET_WIDGET_SIZE         0x00000008
#define START_WIDGET            0x00000010
#define STOP_WIDGET             0x00000020
#define GIVE_WIDGET             0x00000040
#define TAKE_WIDGET             0x00000080


    NTSTATUS Status;

    HANDLE SimpleToken;
    HANDLE TokenWithGroups;
    HANDLE TokenWithDefaultOwner;
    HANDLE TokenWithPrivileges;
    HANDLE TokenWithDefaultDacl;

    HANDLE Token;
    HANDLE ImpersonationToken;

    HANDLE PrimaryToken;

    HANDLE AnonymousToken;

    OBJECT_ATTRIBUTES PrimaryTokenAttributes;
    PSECURITY_DESCRIPTOR PrimarySecurityDescriptor;
    SECURITY_QUALITY_OF_SERVICE PrimarySecurityQos;

    OBJECT_ATTRIBUTES ImpersonationTokenAttributes;
    PSECURITY_DESCRIPTOR ImpersonationSecurityDescriptor;
    SECURITY_QUALITY_OF_SERVICE ImpersonationSecurityQos;

    OBJECT_ATTRIBUTES AnonymousTokenAttributes;
    PSECURITY_DESCRIPTOR AnonymousSecurityDescriptor;
    SECURITY_QUALITY_OF_SERVICE AnonymousSecurityQos;

    ULONG DisabledGroupAttributes;
    ULONG OptionalGroupAttributes;
    ULONG NormalGroupAttributes;
    ULONG OwnerGroupAttributes;

    ULONG LengthAvailable;
    ULONG CurrentLength;


    TIME_FIELDS TempTimeFields = {3000, 1, 1, 1, 1, 1, 1, 1};
    LARGE_INTEGER NoExpiration;

    LUID DummyAuthenticationId;
    LUID SystemAuthenticationId = SYSTEM_LUID;

    TOKEN_SOURCE TestSource = {"SE: TEST", 0};

    PSID Owner;
    PSID Group;
    PACL Dacl;

    PSID TempOwner;
    PSID TempGroup;
    PACL TempDacl;





////////////////////////////////////////////////////////////////
//                                                            //
// Initialization Routine                                     //
//                                                            //
////////////////////////////////////////////////////////////////

BOOLEAN
TestTokenInitialize()
{

    TSeVariableInitialization();    // Initialize global variables


    DisabledGroupAttributes =  (SE_GROUP_ENABLED_BY_DEFAULT);

    OptionalGroupAttributes =  (SE_GROUP_ENABLED_BY_DEFAULT |
                                SE_GROUP_ENABLED
                                );
    NormalGroupAttributes =    (SE_GROUP_MANDATORY          |
                                SE_GROUP_ENABLED_BY_DEFAULT |
                                SE_GROUP_ENABLED
                                );
    OwnerGroupAttributes  =    (SE_GROUP_MANDATORY          |
                                SE_GROUP_ENABLED_BY_DEFAULT |
                                SE_GROUP_ENABLED            |
                                SE_GROUP_OWNER
                                );


    PrimarySecurityDescriptor =
        (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 );

    InitializeObjectAttributes(
        &PrimaryTokenAttributes,
        NULL,
        OBJ_INHERIT,
        NULL,
        NULL
        );


    ImpersonationSecurityDescriptor =
        (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 );

    ImpersonationSecurityQos.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE);
    ImpersonationSecurityQos.ImpersonationLevel = SecurityImpersonation;
    ImpersonationSecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    ImpersonationSecurityQos.EffectiveOnly = FALSE;

    InitializeObjectAttributes(
        &ImpersonationTokenAttributes,
        NULL,
        OBJ_INHERIT,
        NULL,
        NULL
        );
    ImpersonationTokenAttributes.SecurityQualityOfService =
        &ImpersonationSecurityQos;


    AnonymousSecurityDescriptor =
        (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 );

    AnonymousSecurityQos.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE);
    AnonymousSecurityQos.ImpersonationLevel = SecurityAnonymous;
    AnonymousSecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    AnonymousSecurityQos.EffectiveOnly = FALSE;

    InitializeObjectAttributes(
        &AnonymousTokenAttributes,
        NULL,
        OBJ_INHERIT,
        NULL,
        NULL
        );
    AnonymousTokenAttributes.SecurityQualityOfService =
        &AnonymousSecurityQos;


    //
    // Build an ACL for use.
    //

    Dacl        = (PACL)TstAllocatePool( PagedPool, 256 );

    Dacl->AclRevision=ACL_REVISION;
    Dacl->Sbz1=0;
    Dacl->Sbz2=0;
    Dacl->AclSize=256;
    Dacl->AceCount=0;


    //
    // Set up expiration times
    //

    TempTimeFields.Year = 3000;
    TempTimeFields.Month = 1;
    TempTimeFields.Day = 1;
    TempTimeFields.Hour = 1;
    TempTimeFields.Minute = 1;
    TempTimeFields.Second = 1;
    TempTimeFields.Milliseconds = 1;
    TempTimeFields.Weekday = 1;

    RtlTimeFieldsToTime( &TempTimeFields, &NoExpiration );


    //
    // Use a dummy authentication ID for a while.
    //

    DummyAuthenticationId = FredLuid;


    //
    // Use a token source specific to security test
    //

    NtAllocateLocallyUniqueId( &(TestSource.SourceIdentifier) );

    DbgPrint("Done.\n");

    return TRUE;
}


BOOLEAN
CreateDAclToken()
{

    BOOLEAN CompletionStatus = TRUE;

    TOKEN_USER UserId;
    TOKEN_PRIMARY_GROUP PrimaryGroup;
    PTOKEN_GROUPS GroupIds;
    PTOKEN_PRIVILEGES Privileges;
    TOKEN_DEFAULT_DACL DefaultDacl;
    TOKEN_OWNER Owner;

    PSECURITY_DESCRIPTOR Widget1SecurityDescriptor;

    NTSTATUS AccessStatus;

    ACCESS_MASK GrantedAccess;

    PACCESS_ALLOWED_ACE AllowBarneySetColor;
    PACCESS_ALLOWED_ACE AllowFredSetColor;

    PACCESS_DENIED_ACE  DenyPebblesSetColor;

    PACCESS_ALLOWED_ACE AllowPebblesSetColor;
    PACCESS_DENIED_ACE  DenyFredSetColor;
    PACCESS_ALLOWED_ACE AllowBarneySetSize;
    PACCESS_ALLOWED_ACE AllowPebblesSetSize;

    PACCESS_ALLOWED_ACE AllowPebblesGetColor;
    PACCESS_ALLOWED_ACE AllowPebblesGetSize;

    USHORT AllowBarneySetColorLength;
    USHORT AllowFredSetColorLength;
    USHORT DenyPebblesSetColorLength;

    USHORT AllowPebblesSetColorLength;
    USHORT DenyFredSetColorLength;
    USHORT AllowBarneySetSizeLength;
    USHORT AllowPebblesSetSizeLength;

    USHORT AllowPebblesGetColorLength;
    USHORT AllowPebblesGetSizeLength;


    DbgPrint("\n");

    GroupIds = (PTOKEN_GROUPS)TstAllocatePool( PagedPool,
                                               GROUP_IDS_LENGTH
                                               );

    Privileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool,
                                                     PRIVILEGES_LENGTH
                                                     );

    DefaultDacl.DefaultDacl = (PACL)TstAllocatePool( PagedPool,
                                                     DEFAULT_DACL_LENGTH
                                                     );


    //
    // Create a token with default DACL
    //

    DbgPrint("Se:     Create Token With Default Dacl ...                     ");

    GroupIds->GroupCount = GROUP_COUNT;

    GroupIds->Groups[FLINTSTONE_INDEX].Sid  = FlintstoneSid;
    GroupIds->Groups[CHILD_INDEX].Sid       = ChildSid;
    GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid;
    GroupIds->Groups[WORLD_INDEX].Sid       = WorldSid;

    GroupIds->Groups[FLINTSTONE_INDEX].Attributes  = OwnerGroupAttributes;
    GroupIds->Groups[CHILD_INDEX].Attributes       = OptionalGroupAttributes;
    GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes;
    GroupIds->Groups[WORLD_INDEX].Attributes       = NormalGroupAttributes;

    UserId.User.Sid = PebblesSid;
    UserId.User.Attributes = 0;

    Owner.Owner = FlintstoneSid;

    Privileges->PrivilegeCount = PRIVILEGE_COUNT;

    Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege;
    Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege;
    Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0;
    Privileges->Privileges[SECURITY_INDEX].Attributes = 0;

    PrimaryGroup.PrimaryGroup = FlintstoneSid;

    Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION);

    ASSERT(NT_SUCCESS(Status) );

    Status = NtCreateToken(
                 &PrimaryToken,            // Handle
                 (TOKEN_ALL_ACCESS),       // DesiredAccess
                 &PrimaryTokenAttributes,  // ObjectAttributes
                 TokenPrimary,             // TokenType
                 &DummyAuthenticationId,   // Authentication LUID
                 &NoExpiration,            // Expiration Time
                 &UserId,                  // Owner ID
                 GroupIds,                 // Group IDs
                 Privileges,               // Privileges
                 &Owner,                   // Owner
                 &PrimaryGroup,            // Primary Group
                 &DefaultDacl,             // Default Dacl
                 &TestSource               // TokenSource
                 );

    if (NT_SUCCESS(Status)) {
        DbgPrint("Succeeded.\n");
    } else {
        DbgPrint("********** Failed ************\n");
        DbgPrint("Status is: 0x%lx \n", Status);
        CompletionStatus = FALSE;
    }

    ASSERT(NT_SUCCESS(Status));



    //
    // Create an impersonation token, Impersonation level = Impersonation
    //

    DbgPrint("Se:     Create an impersonation token ...                      ");

    GroupIds->GroupCount = GROUP_COUNT;

    GroupIds->Groups[FLINTSTONE_INDEX].Sid  = FlintstoneSid;
    GroupIds->Groups[CHILD_INDEX].Sid       = ChildSid;
    GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid;
    GroupIds->Groups[WORLD_INDEX].Sid       = WorldSid;

    GroupIds->Groups[FLINTSTONE_INDEX].Attributes  = OwnerGroupAttributes;
    GroupIds->Groups[CHILD_INDEX].Attributes       = OptionalGroupAttributes;
    GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes;
    GroupIds->Groups[WORLD_INDEX].Attributes       = NormalGroupAttributes;

    UserId.User.Sid = PebblesSid;
    UserId.User.Attributes = 0;

    Owner.Owner = FlintstoneSid;

    Privileges->PrivilegeCount = PRIVILEGE_COUNT;

    Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege;
    Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege;
    Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0;
    Privileges->Privileges[SECURITY_INDEX].Attributes = 0;

    PrimaryGroup.PrimaryGroup = FlintstoneSid;

    Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION);

    ASSERT(NT_SUCCESS(Status) );

    Status = NtCreateToken(
                 &ImpersonationToken,      // Handle
                 (TOKEN_ALL_ACCESS),       // DesiredAccess
                 &ImpersonationTokenAttributes,  // ObjectAttributes
                 TokenImpersonation,       // TokenType
                 &DummyAuthenticationId,   // Authentication LUID
                 &NoExpiration,            // Expiration Time
                 &UserId,                  // Owner ID
                 GroupIds,                 // Group IDs
                 Privileges,               // Privileges
                 &Owner,                   // Owner
                 &PrimaryGroup,            // Primary Group
                 &DefaultDacl,             // Default Dacl
                 &TestSource               // TokenSource
                 );

    if (NT_SUCCESS(Status)) {
        DbgPrint("Succeeded.\n");
    } else {
        DbgPrint("********** Failed ************\n");
        DbgPrint("Status is: 0x%lx \n", Status);
        CompletionStatus = FALSE;
    }

    ASSERT(NT_SUCCESS(Status));

//
//    Attach tokens to process
//

    NtSetInformationProcess(
        NtCurrentProcess(),
        ProcessAccessToken,
        &PrimaryToken,
        sizeof( PHANDLE ));


    NtSetInformationThread(
        NtCurrentThread(),
        ThreadImpersonationToken,
        &ImpersonationToken,
        sizeof( PHANDLE ));



//  Create some ACEs

//    AllowBarneySetColor

    AllowBarneySetColorLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) +
                                SeLengthSid( BarneySid ));

    AllowBarneySetColor = (PVOID) TstAllocatePool ( PagedPool, AllowBarneySetColorLength );

    AllowBarneySetColor->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    AllowBarneySetColor->Header.AceSize = AllowBarneySetColorLength;
    AllowBarneySetColor->Header.AceFlags = 0;

    AllowBarneySetColor->Mask = SET_WIDGET_COLOR;

    RtlCopySid(
            SeLengthSid( BarneySid ),
            &(AllowBarneySetColor->SidStart),
            BarneySid );


//    DenyPebblesSetColor

    DenyPebblesSetColorLength = (USHORT)(sizeof( ACCESS_DENIED_ACE ) - sizeof( ULONG ) +
                                SeLengthSid( BarneySid ));

    DenyPebblesSetColor = (PVOID) TstAllocatePool ( PagedPool, DenyPebblesSetColorLength );

    DenyPebblesSetColor->Header.AceType = ACCESS_DENIED_ACE_TYPE;
    DenyPebblesSetColor->Header.AceSize = DenyPebblesSetColorLength;
    DenyPebblesSetColor->Header.AceFlags = 0;

    DenyPebblesSetColor->Mask = SET_WIDGET_COLOR;

    RtlCopySid(
            SeLengthSid( PebblesSid ),
            &(DenyPebblesSetColor->SidStart),
            PebblesSid );


//    AllowFredSetColor

    AllowFredSetColorLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) +
                                SeLengthSid( FredSid ));

    AllowFredSetColor = (PVOID) TstAllocatePool ( PagedPool, AllowFredSetColorLength );

    AllowFredSetColor->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    AllowFredSetColor->Header.AceSize = AllowFredSetColorLength;
    AllowFredSetColor->Header.AceFlags = 0;

    AllowFredSetColor->Mask = SET_WIDGET_COLOR;

    RtlCopySid(
            SeLengthSid( FredSid ),
            &(AllowFredSetColor->SidStart),
            FredSid );




//    AllowPebblesSetColor


    AllowPebblesSetColorLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) +
                                SeLengthSid( PebblesSid ));

    AllowPebblesSetColor = (PVOID) TstAllocatePool ( PagedPool, AllowPebblesSetColorLength );

    AllowPebblesSetColor->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    AllowPebblesSetColor->Header.AceSize = AllowPebblesSetColorLength;
    AllowPebblesSetColor->Header.AceFlags = 0;

    AllowPebblesSetColor->Mask = SET_WIDGET_COLOR;

    RtlCopySid(
            SeLengthSid( PebblesSid ),
            &(AllowPebblesSetColor->SidStart),
            PebblesSid );


//    DenyFredSetColor

    DenyFredSetColorLength = (USHORT)(sizeof( ACCESS_DENIED_ACE ) - sizeof( ULONG ) +
                                SeLengthSid( FredSid ));

    DenyFredSetColor = (PVOID) TstAllocatePool ( PagedPool, DenyFredSetColorLength );

    DenyFredSetColor->Header.AceType = ACCESS_DENIED_ACE_TYPE;
    DenyFredSetColor->Header.AceSize = DenyFredSetColorLength;
    DenyFredSetColor->Header.AceFlags = 0;

    DenyFredSetColor->Mask = SET_WIDGET_COLOR;

    RtlCopySid(
            SeLengthSid( FredSid ),
            &(DenyFredSetColor->SidStart),
            FredSid );

//    AllowBarneySetSize

    AllowBarneySetSizeLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) +
                                SeLengthSid( BarneySid ));

    AllowBarneySetSize = (PVOID) TstAllocatePool ( PagedPool, AllowBarneySetSizeLength );

    AllowBarneySetSize->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    AllowBarneySetSize->Header.AceSize = AllowBarneySetSizeLength;
    AllowBarneySetSize->Header.AceFlags = 0;

    AllowBarneySetSize->Mask = SET_WIDGET_SIZE;

    RtlCopySid(
            SeLengthSid( BarneySid ),
            &(AllowBarneySetSize->SidStart),
            BarneySid );

//    AllowPebblesSetSize

    AllowPebblesSetSizeLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) +
                                SeLengthSid( PebblesSid ));

    AllowPebblesSetSize = (PVOID) TstAllocatePool ( PagedPool, AllowPebblesSetSizeLength );

    AllowPebblesSetSize->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    AllowPebblesSetSize->Header.AceSize = AllowPebblesSetSizeLength;
    AllowPebblesSetSize->Header.AceFlags = 0;

    AllowPebblesSetSize->Mask = SET_WIDGET_SIZE;

    RtlCopySid(
            SeLengthSid( PebblesSid ),
            &(AllowPebblesSetSize->SidStart),
            PebblesSid );


//    AllowPebblesGetSize

    AllowPebblesGetSizeLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) +
                                SeLengthSid( PebblesSid ));

    AllowPebblesGetSize = (PVOID) TstAllocatePool ( PagedPool, AllowPebblesGetSizeLength );

    AllowPebblesGetSize->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    AllowPebblesGetSize->Header.AceSize = AllowPebblesGetSizeLength;
    AllowPebblesGetSize->Header.AceFlags = 0;

    AllowPebblesGetSize->Mask = SET_WIDGET_SIZE;

    RtlCopySid(
            SeLengthSid( PebblesSid ),
            &(AllowPebblesGetSize->SidStart),
            PebblesSid );


//    AllowPebblesGetColor

    AllowPebblesGetColorLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) +
                                SeLengthSid( PebblesSid ));

    AllowPebblesGetColor = (PVOID) TstAllocatePool ( PagedPool, AllowPebblesGetColorLength );

    AllowPebblesGetColor->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    AllowPebblesGetColor->Header.AceSize = AllowPebblesGetColorLength;
    AllowPebblesGetColor->Header.AceFlags = 0;

    AllowPebblesGetColor->Mask = SET_WIDGET_COLOR;

    RtlCopySid(
            SeLengthSid( PebblesSid ),
            &(AllowPebblesGetColor->SidStart),
            PebblesSid );

//
//    Create some ACLs that we can put into a Security Descriptor
//
    DbgBreakPoint();

//
//    Dacl
//
//  +----------------+    +----------------+   +----------------+
//  |  1st ACE       |    |  2nd ACE       |   |  3rd ACE       |
//  +----------------+    +----------------+   +----------------+
//  |  AccessAllowed |    |  AccessDenied  |   |  AccessAllowed |
//  +----------------+    +----------------+   +----------------+
//  |  BARNEY        |    |  PEBBLES       |   |  FRED          |
//  +----------------+    +----------------+   +----------------+
//  |  SetWidgeColor |    |  SetWidgeColor |   |  SetWidgeColor |
//  +----------------+    +----------------+   +----------------+
//

    Dacl = (PACL) TstAllocatePool ( PagedPool,  2048 );

    RtlCreateAcl( Dacl, 2048, ACL_REVISION);


    RtlAddAce ( Dacl,
                ACL_REVISION,
                0,
                AllowBarneySetColor,
                AllowBarneySetColorLength );

    RtlAddAce ( Dacl,
                ACL_REVISION,
                1,
                DenyPebblesSetColor,
                DenyPebblesSetColorLength );

    RtlAddAce ( Dacl,
                ACL_REVISION,
                2,
                DenyFredSetColor,
                AllowFredSetColorLength );

    DumpAcl (Dacl);





//  Create a security descriptor
//
//  Owner = Pebbles
//  Group = Flintstone
//  Dacl  = Dacl
//  Sacl  = NULL
//

    Widget1SecurityDescriptor =
        (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 );

    RtlCreateSecurityDescriptor( Widget1SecurityDescriptor,
                                 1 );


    RtlSetOwnerSecurityDescriptor( Widget1SecurityDescriptor,
                                   PebblesSid,
                                   FALSE );

    RtlSetGroupSecurityDescriptor( Widget1SecurityDescriptor,
                                   FlintstoneSid,
                                   FALSE );

    RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor,
                                  TRUE,
                                  Dacl,
                                  FALSE );

    RtlSetSaclSecurityDescriptor( Widget1SecurityDescriptor,
                                  FALSE,
                                  NULL,
                                  NULL );

//  See if Pebbles is allowed SET_WIDGET_COLOR (should be denied)

    Status = NtAccessCheck( Widget1SecurityDescriptor,
                   PrimaryToken,
                   (ACCESS_MASK) SET_WIDGET_COLOR,
                   &GrantedAccess,
                   &AccessStatus );

//    DbgBreakPoint();

    ASSERT(NT_SUCCESS(Status));

    ASSERT(!NT_SUCCESS(AccessStatus));

    ASSERT(GrantedAccess == NULL);


//  Update Dacl to be the following:
//
//    Dacl2
//
//  +----------------+    +----------------+   +----------------+
//  |  1st ACE       |    |  2nd ACE       |   |  3rd ACE       |
//  +----------------+    +----------------+   +----------------+
//  |  AccessAllowed |    |  AccessAllowed |   |  AccessDenied  |
//  +----------------+    +----------------+   +----------------+
//  |  BARNEY        |    |  PEBBLES       |   |  FRED          |
//  +----------------+    +----------------+   +----------------+
//  |  SetWidgeColor |    |  SetWidgeColor |   |  SetWidgeColor |
//  +----------------+    +----------------+   +----------------+
//

//  Delete 2nd Ace

    RtlDeleteAce (Dacl, 1);

    RtlAddAce ( Dacl,
                ACL_REVISION,
                1,
                AllowPebblesSetColor,
                AllowPebblesSetColorLength );

    RtlDeleteAce ( Dacl, 2 );

    RtlAddAce ( Dacl,
                ACL_REVISION,
                1,
                DenyFredSetColor,
                DenyFredSetColorLength );




//  Change the security descriptor to use updated Dacl
//
//  Owner = Pebbles
//  Group = Flintstone
//  Dacl  = Dacl2
//  Sacl  = NULL
//

    RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor,
                                  TRUE,
                                  Dacl,
                                  FALSE );

//  See if Pebbles is allowed SET_WIDGET_COLOR (should be permitted)

    Status = NtAccessCheck( Widget1SecurityDescriptor,
                            PrimaryToken,
                            (ACCESS_MASK) SET_WIDGET_COLOR,
                            &GrantedAccess,
                            &AccessStatus );


    ASSERT(NT_SUCCESS(Status));

    ASSERT(NT_SUCCESS(AccessStatus));

    ASSERT(GrantedAccess == (ACCESS_MASK)SET_WIDGET_COLOR);

//
//    Dacl3
//
//  +----------------+    +----------------+   +----------------+
//  |  1st ACE       |    |  2nd ACE       |   |  3rd ACE       |
//  +----------------+    +----------------+   +----------------+
//  |  AccessAllowed |    |  AccessAllowed |   |  AccessDenied  |
//  +----------------+    +----------------+   +----------------+
//  |  BARNEY        |    |  PEBBLES       |   |  FRED          |
//  +----------------+    +----------------+   +----------------+
//  |  SetWidgeColor |    |  SetWidgeColor |   |  SetWidgeColor |
//  +----------------+    +----------------+   +----------------+
//
//  +----------------+    +----------------+
//  |  4th ACE       |    |  5th ACE       |
//  +----------------+    +----------------+
//  |  AccessAllowed |    |  AccessAllowed |
//  +----------------+    +----------------+
//  |  BARNEY        |    |  PEBBLES       |
//  +----------------+    +----------------+
//  |  SetWidgeSize  |    |  SetWidgeSize  |
//  +----------------+    +----------------+
//


    RtlAddAce ( Dacl,
                ACL_REVISION,
                MAXULONG,
                AllowBarneySetSize,
                AllowBarneySetSizeLength );

    RtlAddAce ( Dacl,
                ACL_REVISION,
                MAXULONG,
                AllowPebblesSetSize,
                AllowPebblesSetSizeLength );

//  Change the security descriptor to use Dacl3
//
//  Owner = Pebbles
//  Group = Flintstone
//  Dacl  = Dacl3
//  Sacl  = NULL
//

    RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor,
                                  TRUE,
                                  Dacl,
                                  FALSE );

//  Request MAXIMUM_ACCESS for Pebbles.  Should get back SetWidgetSize
//  and SetWidgetColor

    Status = NtAccessCheck( Widget1SecurityDescriptor,
                            PrimaryToken,
                            (ACCESS_MASK) MAXIMUM_ALLOWED,
                            &GrantedAccess,
                            &AccessStatus );


    ASSERT(NT_SUCCESS(Status));

    ASSERT(NT_SUCCESS(AccessStatus));

    ASSERT(GrantedAccess == (ACCESS_MASK) (SET_WIDGET_COLOR | SET_WIDGET_SIZE));


//
//    Dacl4
//
//  +----------------+    +----------------+   +----------------+
//  |  1st ACE       |    |  2nd ACE       |   |  3rd ACE       |
//  +----------------+    +----------------+   +----------------+
//  |  AccessAllowed |    |  AccessAllowed |   |  AccessDenied  |
//  +----------------+    +----------------+   +----------------+
//  |  BARNEY        |    |  PEBBLES       |   |  FRED          |
//  +----------------+    +----------------+   +----------------+
//  |  SetWidgeColor |    |  SetWidgeColor |   |  SetWidgeColor |
//  +----------------+    +----------------+   +----------------+
//
//  +----------------+    +----------------+   +----------------+
//  |  4th ACE       |    |  5th ACE       |   |  6th ACE       |
//  +----------------+    +----------------+   +----------------+
//  |  AccessAllowed |    |  AccessAllowed |   |  AccessDenied  |
//  +----------------+    +----------------+   +----------------+
//  |  BARNEY        |    |  PEBBLES       |   |  PEBBLES       |
//  +----------------+    +----------------+   +----------------+
//  |  SetWidgeSize  |    |  SetWidgeSize  |   |  SetWidgeColor |
//  +----------------+    +----------------+   +----------------+
//

    RtlAddAce ( Dacl,
                ACL_REVISION,
                MAXULONG,
                DenyPebblesSetColor,
                DenyPebblesSetColorLength );

    RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor,
                                  TRUE,
                                  Dacl,
                                  FALSE );

//  Request MAXIMUM_ACCESS for Pebbles.  Should get back SetWidgetSize
//  and SetWidgetColor

    Status = NtAccessCheck( Widget1SecurityDescriptor,
                            PrimaryToken,
                            (ACCESS_MASK) MAXIMUM_ALLOWED,
                            &GrantedAccess,
                            &AccessStatus );


    ASSERT(NT_SUCCESS(Status));

    ASSERT(NT_SUCCESS(AccessStatus));

    ASSERT(GrantedAccess == (ACCESS_MASK) (SET_WIDGET_COLOR | SET_WIDGET_SIZE));


//
//    Dacl5
//
//  +----------------+    +----------------+   +----------------+
//  |  1st ACE       |    |  2nd ACE       |   |  3rd ACE       |
//  +----------------+    +----------------+   +----------------+
//  |  AccessAllowed |    |  AccessDenied  |   |  AccessDenied  |
//  +----------------+    +----------------+   +----------------+
//  |  BARNEY        |    |  PEBBLES       |   |  FRED          |
//  +----------------+    +----------------+   +----------------+
//  |  SetWidgeColor |    |  SetWidgeColor |   |  SetWidgeColor |
//  +----------------+    +----------------+   +----------------+
//
//  +----------------+    +----------------+   +----------------+
//  |  4th ACE       |    |  5th ACE       |   |  6th ACE       |
//  +----------------+    +----------------+   +----------------+
//  |  AccessAllowed |    |  AccessAllowed |   |  AccessAllowed |
//  +----------------+    +----------------+   +----------------+
//  |  BARNEY        |    |  PEBBLES       |   |  PEBBLES       |
//  +----------------+    +----------------+   +----------------+
//  |  SetWidgeSize  |    |  SetWidgeSize  |   |  SetWidgeColor |
//  +----------------+    +----------------+   +----------------+
//

    RtlDeleteAce (Dacl, 1);

    RtlAddAce ( Dacl,
                ACL_REVISION,
                1,
                DenyPebblesSetColor,
                DenyPebblesSetColorLength );

    RtlDeleteAce (Dacl, 5);

    RtlAddAce ( Dacl,
                ACL_REVISION,
                MAXULONG,
                AllowPebblesSetColor,
                AllowPebblesSetColorLength );


    DumpAcl ( Dacl );

    RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor,
                                  TRUE,
                                  Dacl,
                                  FALSE );

//  Request MAXIMUM_ACCESS for Pebbles.  Should get back SetWidgetSize

    Status = NtAccessCheck( Widget1SecurityDescriptor,
                            PrimaryToken,
                            (ACCESS_MASK) MAXIMUM_ALLOWED,
                            &GrantedAccess,
                            &AccessStatus );


    ASSERT(NT_SUCCESS(Status));

    ASSERT(NT_SUCCESS(AccessStatus));

    ASSERT(GrantedAccess == (ACCESS_MASK) SET_WIDGET_SIZE);


//
//    Dacl6
//
//  +----------------+    +----------------+   +----------------+
//  |  1st ACE       |    |  2nd ACE       |   |  3rd ACE       |
//  +----------------+    +----------------+   +----------------+
//  |  AccessAllowed |    |  AccessDenied  |   |  AccessDenied  |
//  +----------------+    +----------------+   +----------------+
//  |  BARNEY        |    |  PEBBLES       |   |  FRED          |
//  +----------------+    +----------------+   +----------------+
//  |  SetWidgeColor |    |  SetWidgeColor |   |  SetWidgeColor |
//  +----------------+    +----------------+   +----------------+
//
//  +----------------+    +----------------+   +----------------+
//  |  4th ACE       |    |  5th ACE       |   |  6th ACE       |
//  +----------------+    +----------------+   +----------------+
//  |  AccessAllowed |    |  AccessAllowed |   |  AccessAllowed |
//  +----------------+    +----------------+   +----------------+
//  |  BARNEY        |    |  PEBBLES       |   |  PEBBLES       |
//  +----------------+    +----------------+   +----------------+
//  |  SetWidgeSize  |    |  SetWidgeSize  |   |  SetWidgeColor |
//  +----------------+    +----------------+   +----------------+
//
//  +----------------+    +----------------+
//  |  7th ACE       |    |  8th ACE       |
//  +----------------+    +----------------+
//  |  AccessAllowed |    |  AccessAllowed |
//  +----------------+    +----------------+
//  |  PEBBLES       |    |  PEBBLES       |
//  +----------------+    +----------------+
//  |  GetWidgeSize  |    |  GetWidgeColor |
//  +----------------+    +----------------+
//

    RtlAddAce ( Dacl,
                ACL_REVISION,
                MAXULONG,
                AllowPebblesGetSize,
                AllowPebblesGetSizeLength );

    RtlAddAce ( Dacl,
                ACL_REVISION,
                MAXULONG,
                AllowPebblesGetColor,
                AllowPebblesGetColorLength );

    DumpAcl ( Dacl );

    RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor,
                                  TRUE,
                                  Dacl,
                                  FALSE );

//  Request MAXIMUM_ACCESS for Pebbles.  Should get back SetWidgetSize

    Status = NtAccessCheck( Widget1SecurityDescriptor,
                            PrimaryToken,
                            (ACCESS_MASK) MAXIMUM_ALLOWED,
                            &GrantedAccess,
                            &AccessStatus );


    ASSERT(NT_SUCCESS(Status));

    ASSERT(NT_SUCCESS(AccessStatus));

    ASSERT(GrantedAccess == (ACCESS_MASK) SET_WIDGET_SIZE);



    return(TRUE);


}


/////////////////////////////////////////////////////////////////////
//                                                                 //
//                                                                 //
//    Main test entry point                                        //
//                                                                 //
//                                                                 //
/////////////////////////////////////////////////////////////////////


BOOLEAN
CTAccess()
{

    BOOLEAN Result = TRUE;

    if (!TSeVariableInitialization()) {
        DbgPrint("Se:    Failed to initialize global test variables.\n");
        return FALSE;
    }

    DbgPrint("Se:   Initialization...");
    TestTokenInitialize();
    CreateDAclToken();

}


//
//  Debug support routine
//


typedef struct _STANDARD_ACE {
    ACE_HEADER Header;
    ACCESS_MASK Mask;
    PSID Sid;
} STANDARD_ACE;
typedef STANDARD_ACE *PSTANDARD_ACE;



VOID
DumpAcl (
    IN PACL Acl
    )

/*++

Routine Description:

    This routine dumps via (DbgPrint) an Acl for debug purposes.  It is
    specialized to dump standard aces.

Arguments:

    Acl - Supplies the Acl to dump

Return Value:

    None

--*/


{
    ULONG i;
    PSTANDARD_ACE Ace;

    DbgPrint("DumpAcl @ %8lx", Acl);

    //
    //  Check if the Acl is null
    //

    if (Acl == NULL) {

        return;

    }

    //
    //  Dump the Acl header
    //

    DbgPrint(" Revision: %02x", Acl->AclRevision);
    DbgPrint(" Size: %04x", Acl->AclSize);
    DbgPrint(" AceCount: %04x\n", Acl->AceCount);

    //
    //  Now for each Ace we want do dump it
    //

    for (i = 0, Ace = FirstAce(Acl);
         i < Acl->AceCount;
         i++, Ace = NextAce(Ace) ) {

        //
        //  print out the ace header
        //

        DbgPrint(" AceHeader: %08lx ", *(PULONG)Ace);

        //
        //  special case on the standard ace types
        //

        if ((Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) ||
            (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) ||
            (Ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE) ||
            (Ace->Header.AceType == SYSTEM_ALARM_ACE_TYPE)) {

            //
            //  The following array is indexed by ace types and must
            //  follow the allowed, denied, audit, alarm seqeuence
            //

            static PCHAR AceTypes[] = { "Access Allowed",
                                        "Access Denied ",
                                        "System Audit  ",
                                        "System Alarm  "
                                      };

            DbgPrint(AceTypes[Ace->Header.AceType]);
            DbgPrint("\nAccess Mask: %08lx ", Ace->Mask);

        } else {

            DbgPrint("Unknown Ace Type\n");

        }

        DbgPrint("\n");

        DbgPrint("AceSize = %d\n",Ace->Header.AceSize);
        DbgPrint("Ace Flags = ");
        if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE) {
            DbgPrint("OBJECT_INHERIT_ACE\n");
            DbgPrint("                   ");
        }
        if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE) {
            DbgPrint("CONTAINER_INHERIT_ACE\n");
            DbgPrint("                   ");
        }

        if (Ace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) {
            DbgPrint("NO_PROPAGATE_INHERIT_ACE\n");
            DbgPrint("                   ");
        }

        if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) {
            DbgPrint("INHERIT_ONLY_ACE\n");
            DbgPrint("                   ");
        }


        if (Ace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) {
            DbgPrint("SUCCESSFUL_ACCESS_ACE_FLAG\n");
            DbgPrint("            ");
        }

        if (Ace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) {
            DbgPrint("FAILED_ACCESS_ACE_FLAG\n");
            DbgPrint("            ");
        }

        DbgPrint("\n");


    }

}
