/*++

Copyright (c) 1990  Microsoft Corporation

Module Name:

    tmachine.c

Abstract:

    This module tests token duplication.

Author:

    Jim Kelly    (JimK) 8-Feb-1994

Environment:

    User Mode - Win32

Revision History:


--*/







///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Includes                                                                  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <nt.h>
#include <ntsam.h>
#include <ntsamp.h>
#include <ntlsa.h>
#include <ntrpcp.h>     // prototypes for MIDL user functions
#include <seopaque.h>
#include <string.h>



#ifdef NOT_PART_OF_PROGRAM


///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Definitions                                                               //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////





#define TMPP_USER_NAME_ADMIN           "Administrator"
#define TMPP_USER_NAME_GUEST           "Guest"
#define TMPP_GROUP_NAME_ADMINS         "Domain Admins"
#define TMPP_GROUP_NAME_USERS          "Domain Users"
#define TMPP_GROUP_NAME_NONE           "None"
#define TMPP_ALIAS_NAME_ADMINS         "Administrators"
#define TMPP_ALIAS_NAME_SYSTEM_OPS     "System Operators"
#define TMPP_ALIAS_NAME_POWER_USERS    "Power Users"
#define TMPP_ALIAS_NAME_USERS          "Users"
#define TMPP_ALIAS_NAME_GUESTS         "Guests"
#define TMPP_ALIAS_NAME_ACCOUNT_OPS    "Account Operators"
#define TMPP_ALIAS_NAME_PRINT_OPS      "Print Operators"
#define TMPP_ALIAS_NAME_BACKUP_OPS     "Backup Operators"



#define GROUP_NAME1             "GROUP1"
#define ALIAS_NAME1             "ALIAS1"
#define ALIAS_NAME2             "ALIAS2"
#define USER_NAME1              "USER1"
#define USER_NAME2              "USER2"
#define USER_NAME3              "USER3"

// Keep these names not longer than 8 char's until long registry names supported
#define DUMMY_NAME1             "DName1"
#define DUMMY_NAME2             "2emaNuD"

#define DUMMY_STRING1           "This is test string 1"
#define DUMMY_STRING2           "Test String2 - test string 2 - tEST sTRING 2"

#define ALL_NAMES_COUNT         (3)
#define SOME_NAMES_COUNT        (7)
#define NO_NAMES_COUNT          (2)

#define LOOKUP_KNOWN_NAME0      TMPP_USER_NAME_ADMIN
#define LOOKUP_KNOWN_NAME1_A    TMPP_GROUP_NAME_NONE
#define LOOKUP_KNOWN_NAME2_A    TMPP_GROUP_NAME_NONE
#define LOOKUP_KNOWN_NAME1_P    TMPP_GROUP_NAME_USERS
#define LOOKUP_KNOWN_NAME2_P    TMPP_GROUP_NAME_USERS

#define LOOKUP_KNOWN_NAME0_RID  DOMAIN_USER_RID_ADMIN
#define LOOKUP_KNOWN_NAME1_RID  DOMAIN_GROUP_RID_USERS
#define LOOKUP_KNOWN_NAME2_RID  DOMAIN_GROUP_RID_USERS

#define LOOKUP_UNKNOWN_NAME0    "JoeJoe"
#define LOOKUP_UNKNOWN_NAME1    "Tanya"
#define LOOKUP_UNKNOWN_NAME2    "Fred"
#define LOOKUP_UNKNOWN_NAME3    "Anyone"

#define LOOKUP_KNOWN_NAME0_USE  (SidTypeUser)
#define LOOKUP_KNOWN_NAME1_USE  (SidTypeGroup)
#define LOOKUP_KNOWN_NAME2_USE  (SidTypeGroup)


//
// This byte is expected to be different in the DummyLogonHours and
// NoRestrictionLogonHours.
//

#define LOGON_HOURS_DIFFERENT_OFFSET    (5)



///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Global variables                                                          //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

LARGE_INTEGER LargeInteger1,
              LargeInteger2;

UNICODE_STRING DummyName1,
               DummyName2,
               DummyString1,
               DummyString2;

STRING         DummyAnsiString1,
               DummyAnsiString2;

LOGON_HOURS    NoLogonRestriction,
               DummyLogonHours;

CHAR           NoLogonRestrictionBitMask[21],
               DummyLogonHoursBitMask[21];


UNICODE_STRING  AllNames[ALL_NAMES_COUNT],
                SomeNames[SOME_NAMES_COUNT],
                NoNames[NO_NAMES_COUNT];


SID_NAME_USE    AllUses[ALL_NAMES_COUNT],
                SomeUses[SOME_NAMES_COUNT],
                NoUses[NO_NAMES_COUNT];

ULONG           AllRids[ALL_NAMES_COUNT],
                SomeRids[SOME_NAMES_COUNT],
                NoRids[NO_NAMES_COUNT];


PSID            BuiltinDomainSid,
                AccountDomainSid,
                PrimaryDomainSid,
                WorldSid,
                AdminsAliasSid,
                AccountAliasSid;


UNICODE_STRING  BuiltinDomainName,
                AccountDomainName,
                PrimaryDomainName;

BOOLEAN         AccountDomainIsNotPrimaryDomain;


//
// These are NOT mutually exclusive
//

BOOLEAN         BuiltinDomainTest,      // Test the builting domain
                SecurityOperatorTest,   // Test auditing accessibility
                AccountOpAliasTest,     // Test account operator functions
                AdminsAliasTest;        // Test domain admin functions



///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// private macros                                                            //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////


//
// VOID
// TST_SUCCESS_ASSERT( IN NTSTATUS S );
//

#define TST_SUCCESS_ASSERT( S )                                             \
{                                                                           \
    if ( !NT_SUCCESS((S)) ) {                                               \
        printf("\n** SUCCESS STATUS ASSERTION FAILURE **\n");             \
        printf("   Status is:  0x%lx\n", (S) );                           \
        ASSERT(NT_SUCCESS((S)));                                            \
    }                                                                       \
}



///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// private service prototypes                                                //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////




BOOLEAN
TInitialize( VOID );

BOOLEAN
EnableSecurityPrivilege( VOID );

VOID
DetermineTestsToRun( VOID );

VOID
SeeIfSidIsSpecial(
    IN PSID Sid
    );

BOOLEAN
ServerTestSuite(
    PHANDLE ServerHandle,
    PHANDLE DomainHandle,
    PHANDLE BuiltinDomainHandle,
    PSID    *DomainSid
    );

BOOLEAN
SecurityTestSuite(
    HANDLE ServerHandle,
    HANDLE DomainHandle,
    ULONG Pass
    );

BOOLEAN
CheckReturnedSD(
    IN SECURITY_INFORMATION SI,
    IN PSECURITY_DESCRIPTOR SD,
    IN BOOLEAN              PrintTestSuccess
    );


BOOLEAN
DomainTestSuite(
    HANDLE DomainHandle
    );

BOOLEAN
GroupTestSuite(
    HANDLE DomainHandle,
    ULONG  Pass
    );

BOOLEAN
AliasTestSuite(
    HANDLE DomainHandle,
    HANDLE BuiltinDomainHandle,
    PSID DomainSid,
    ULONG  Pass
    );

BOOLEAN
UserTestSuite(
    HANDLE DomainHandle,
    ULONG Pass
    );


NTSTATUS
SampSetDomainPolicy( VOID );


NTSTATUS
SampGetLsaDomainInfo(
    PPOLICY_ACCOUNT_DOMAIN_INFO *PolicyAccountDomainInfo,
    PPOLICY_PRIMARY_DOMAIN_INFO *PolicyPrimaryDomainInfo
    );


//
// The following are in WRAPPERS.C, but are prototyped here since this
// test is the only thing that should ever call them.
//

NTSTATUS
SamTestPrivateFunctionsDomain(
    IN HANDLE DomainHandle
    );

NTSTATUS
SamTestPrivateFunctionsUser(
    IN HANDLE UserHandle
    );


#endif // NOT_PART_OF_PROGRAM

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Routines                                                                  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////



VOID
main (argc, argv)
int argc;
char **argv;

/*++

Routine Description:

    This is the main entry routine for this test.

Arguments:

    NONE


Return Value:




--*/
{
    NTSTATUS
        NtStatus;

    HANDLE
        h1, h2, h3;

    OBJECT_ATTRIBUTES
        ObjectAttributes;

    SECURITY_QUALITY_OF_SERVICE
        Qos;

    //
    // Duplicate our primary token to get an impersonation token.
    // (no security QOS causes duplicate to have Anonymous level)
    //

    NtStatus = NtOpenProcessToken( NtCurrentProcess(),
                                   TOKEN_DUPLICATE,
                                   &h1);
    printf("Test: Open Process Token: 0x%lx\n", NtStatus);

    InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL );
    NtStatus = NtDuplicateToken( h1,
                                 TOKEN_DUPLICATE,
                                 &ObjectAttributes,
                                 FALSE,         // EffectiveOnly
                                 TokenImpersonation,
                                 &h2);
    printf("Test: Duplicate Primary to anonymous Impersonation: 0x%lx\n", NtStatus);


    //
    // Now duplicate that to get a primary
    //
    NtStatus = NtDuplicateToken( h2,
                                 TOKEN_DUPLICATE,
                                 &ObjectAttributes,
                                 FALSE,         // EffectiveOnly
                                 TokenPrimary,
                                 &h3);
    printf("Test: Duplicate anonymous Impersonation to Primary: 0x%lx\n", NtStatus);

    //
    // Now try it again with Impersonate level.
    //

    Qos.Length = sizeof(Qos);
    Qos.ImpersonationLevel = SecurityImpersonation;
    Qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
    Qos.EffectiveOnly = FALSE;

    InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL );
    ObjectAttributes.SecurityQualityOfService = &Qos;

    NtStatus = NtDuplicateToken( h1,
                                 TOKEN_DUPLICATE,
                                 &ObjectAttributes,
                                 FALSE,         // EffectiveOnly
                                 TokenImpersonation,
                                 &h2);
    printf("Test: Duplicate Primary to IMPERSONATE Impersonation: 0x%lx\n", NtStatus);


    //
    // Now duplicate that to get a primary
    //
    NtStatus = NtDuplicateToken( h2,
                                 TOKEN_DUPLICATE,
                                 &ObjectAttributes,
                                 FALSE,         // EffectiveOnly
                                 TokenPrimary,
                                 &h3);
    printf("Test: Duplicate IMPERSONATE Impersonation to Primary: 0x%lx\n", NtStatus);

    return;
}

#ifdef NOT_PART_OF_PROGRAM

BOOLEAN
TInitialize (
    VOID
    )

/*++

Routine Description:

    Initialize test variables, et cetera.

Arguments:

    None.

Return Value:


    Note:


--*/
{
    NTSTATUS NtStatus;
    STRING Name;
    ULONG i;

    SID_IDENTIFIER_AUTHORITY    WorldSidAuthority        = SECURITY_WORLD_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY    DomainSidAuthority       = {0,0,0,0,0,0};
    SID_IDENTIFIER_AUTHORITY    BuiltinAuthority         = SECURITY_NT_AUTHORITY;


    //
    // Get the domain SIDs from the policy database...
    //

    NtStatus = SampSetDomainPolicy();
    ASSERT(NT_SUCCESS(NtStatus));


    //
    // A random large integer value..
    //

    LargeInteger1.LowPart = 1234;
    LargeInteger1.HighPart = 0;

    LargeInteger2.LowPart = 4321;
    LargeInteger2.HighPart = 0;


    RtlInitString( &Name, DUMMY_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &DummyName1, &Name, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);

    RtlInitString( &Name, DUMMY_NAME2 );
    NtStatus = RtlAnsiStringToUnicodeString( &DummyName2, &Name, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    RtlInitString( &DummyAnsiString1, DUMMY_STRING1 );
    NtStatus = RtlAnsiStringToUnicodeString( &DummyString1, &DummyAnsiString1, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);

    RtlInitString( &DummyAnsiString2, DUMMY_STRING2 );
    NtStatus = RtlAnsiStringToUnicodeString( &DummyString2, &DummyAnsiString2, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    DummyLogonHours.UnitsPerWeek = SAM_HOURS_PER_WEEK;
    DummyLogonHours.LogonHours   = &DummyLogonHoursBitMask[0];
    DummyLogonHoursBitMask[LOGON_HOURS_DIFFERENT_OFFSET] = 103; // Any non-zero value

    NoLogonRestriction.UnitsPerWeek = SAM_HOURS_PER_WEEK;
    NoLogonRestriction.LogonHours   = &NoLogonRestrictionBitMask[0];
    for ( i=0; i<(ULONG)((NoLogonRestriction.UnitsPerWeek+7)/8); i++) {
        NoLogonRestrictionBitMask[0] = 0;
    }



    //
    //  Initialize some SIDs
    //


    WorldSid = RtlAllocateHeap( RtlProcessHeap(), 0, RtlLengthRequiredSid(1) );
    ASSERT(WorldSid != NULL);
    RtlInitializeSid( WorldSid, &WorldSidAuthority, 1 );
    *(RtlSubAuthoritySid( WorldSid, 0 )) = SECURITY_WORLD_RID;

    AdminsAliasSid  = RtlAllocateHeap(RtlProcessHeap(), 0,RtlLengthRequiredSid( 2 ));
    ASSERT(AdminsAliasSid != NULL);
    RtlInitializeSid( AdminsAliasSid,   &BuiltinAuthority, 2 );
    *(RtlSubAuthoritySid( AdminsAliasSid,  0 )) = SECURITY_BUILTIN_DOMAIN_RID;
    *(RtlSubAuthoritySid( AdminsAliasSid,  1 )) = DOMAIN_ALIAS_RID_ADMINS;

    AccountAliasSid  = RtlAllocateHeap(RtlProcessHeap(), 0,RtlLengthRequiredSid( 2 ));
    ASSERT(AccountAliasSid != NULL);
    RtlInitializeSid( AccountAliasSid,   &BuiltinAuthority, 2 );
    *(RtlSubAuthoritySid( AccountAliasSid,  0 )) = SECURITY_BUILTIN_DOMAIN_RID;
    *(RtlSubAuthoritySid( AccountAliasSid,  1 )) = DOMAIN_ALIAS_RID_ACCOUNT_OPS;




    //
    // Initialize some stuff for SID and NAME lookup operations
    //

    RtlInitString( &Name, LOOKUP_KNOWN_NAME0 );

    AllUses[0] = LOOKUP_KNOWN_NAME0_USE;  AllRids[0] = LOOKUP_KNOWN_NAME0_RID;
    NtStatus = RtlAnsiStringToUnicodeString( &AllNames[0], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);
    SomeUses[0] = LOOKUP_KNOWN_NAME0_USE;  SomeRids[0] = LOOKUP_KNOWN_NAME0_RID;
    NtStatus = RtlAnsiStringToUnicodeString( &SomeNames[0], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);


    if (AccountDomainIsNotPrimaryDomain == TRUE) {
        RtlInitString( &Name, LOOKUP_KNOWN_NAME1_A );
    } else {
        RtlInitString( &Name, LOOKUP_KNOWN_NAME1_P );
    }
    AllUses[1] = LOOKUP_KNOWN_NAME1_USE;  AllRids[1] = LOOKUP_KNOWN_NAME1_RID;
    NtStatus = RtlAnsiStringToUnicodeString( &AllNames[1], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);
    SomeUses[1] = LOOKUP_KNOWN_NAME1_USE;  SomeRids[1] = LOOKUP_KNOWN_NAME1_RID;
    NtStatus = RtlAnsiStringToUnicodeString( &SomeNames[1], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);

    RtlInitString( &Name, LOOKUP_UNKNOWN_NAME0 );

    SomeUses[2] = SidTypeUnknown;
    NtStatus = RtlAnsiStringToUnicodeString( &SomeNames[2], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);
    NoUses[0] = SidTypeUnknown;
    NtStatus = RtlAnsiStringToUnicodeString( &NoNames[0], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);


    RtlInitString( &Name, LOOKUP_UNKNOWN_NAME1 );

    SomeUses[3] = SidTypeUnknown;
    NtStatus = RtlAnsiStringToUnicodeString( &SomeNames[3], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);
    NoUses[1] = SidTypeUnknown;
    NtStatus = RtlAnsiStringToUnicodeString( &NoNames[1], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);



    RtlInitString( &Name, LOOKUP_UNKNOWN_NAME2 );

    SomeUses[4] = SidTypeUnknown;
    NtStatus = RtlAnsiStringToUnicodeString( &SomeNames[4], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);


    if (AccountDomainIsNotPrimaryDomain == TRUE) {
        RtlInitString( &Name, LOOKUP_KNOWN_NAME2_A );
    } else {
        RtlInitString( &Name, LOOKUP_KNOWN_NAME2_P );
    }
    AllUses[2] = LOOKUP_KNOWN_NAME2_USE;  AllRids[2] = LOOKUP_KNOWN_NAME2_RID;
    NtStatus = RtlAnsiStringToUnicodeString( &AllNames[2], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);
    SomeUses[5] = LOOKUP_KNOWN_NAME2_USE;  SomeRids[5] = LOOKUP_KNOWN_NAME2_RID;
    NtStatus = RtlAnsiStringToUnicodeString( &SomeNames[5], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);



    RtlInitString( &Name, LOOKUP_UNKNOWN_NAME3 );

    SomeUses[6] = SidTypeUnknown;
    NtStatus = RtlAnsiStringToUnicodeString( &SomeNames[6], &Name, TRUE ); TST_SUCCESS_ASSERT(NtStatus);


    DetermineTestsToRun();

    return(TRUE);
}


NTSTATUS
SampSetDomainPolicy(
    )
/*++


Routine Description:

    This routine sets the names and SIDs for the builtin and account domains.
    The builtin account domain has a well known name and SID.
    The account domain has these stored in the Policy database.


    It places the information for these domains in:

            BuiltinDomainSid
            BuiltinDomainName
            AccountDomainSid
            AccountDomainName
            PrimaryDomainSid
            PrimaryDomainName

    It also sets the boolean:

            AccountDomainIsNotPrimaryDomain

    to TRUE if the account domain is found to be different from the
    Primary Domain.

Arguments:

    None.

Return Value:

--*/

{
    NTSTATUS NtStatus;
    PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo;
    PPOLICY_PRIMARY_DOMAIN_INFO PolicyPrimaryDomainInfo;
    SID_IDENTIFIER_AUTHORITY BuiltinAuthority = SECURITY_NT_AUTHORITY;

    //
    // Builtin domain - well-known name and SID
    //

    RtlInitUnicodeString( &BuiltinDomainName, L"Builtin");

    BuiltinDomainSid  = RtlAllocateHeap(RtlProcessHeap(), 0,RtlLengthRequiredSid( 1 ));
    ASSERT( BuiltinDomainSid != NULL );
    RtlInitializeSid( BuiltinDomainSid,   &BuiltinAuthority, 1 );
    *(RtlSubAuthoritySid( BuiltinDomainSid,  0 )) = SECURITY_BUILTIN_DOMAIN_RID;

    //
    // Account domain
    //

    NtStatus = SampGetLsaDomainInfo(
                   &PolicyAccountDomainInfo,
                   &PolicyPrimaryDomainInfo
                   );

    if (!NT_SUCCESS(NtStatus)) {

        return(NtStatus);
    }

    AccountDomainSid = PolicyAccountDomainInfo->DomainSid;
    AccountDomainName = PolicyAccountDomainInfo->DomainName;

    PrimaryDomainSid = PolicyPrimaryDomainInfo->Sid;
    PrimaryDomainName = PolicyPrimaryDomainInfo->Name;

    //
    // Determine whether the account domain is a primary domain.
    //

    AccountDomainIsNotPrimaryDomain =
        !RtlEqualUnicodeString( &PrimaryDomainName, &AccountDomainName, TRUE);

    return(NtStatus);;
}



NTSTATUS
SampGetLsaDomainInfo(
    PPOLICY_ACCOUNT_DOMAIN_INFO *PolicyAccountDomainInfo,
    PPOLICY_PRIMARY_DOMAIN_INFO *PolicyPrimaryDomainInfo
    )

/*++

Routine Description:

    This routine retrieves ACCOUNT domain information from the LSA
    policy database.


Arguments:

    PolicyAccountDomainInfo - Receives a pointer to a
        POLICY_ACCOUNT_DOMAIN_INFO structure containing the account
        domain info.

    PolicyPrimaryDomainInfo - Receives a pointer to a
        POLICY_PRIMARY_DOMAIN_INFO structure containing the Primary
        domain info.


Return Value:

    STATUS_SUCCESS - Succeeded.

    Other status values that may be returned from:

             LsaOpenPolicy()
             LsaQueryInformationPolicy()
--*/

{
    NTSTATUS Status, IgnoreStatus;

    LSA_HANDLE PolicyHandle;
    OBJECT_ATTRIBUTES PolicyObjectAttributes;

    //
    // Open the policy database
    //

    InitializeObjectAttributes( &PolicyObjectAttributes,
                                  NULL,             // Name
                                  0,                // Attributes
                                  NULL,             // Root
                                  NULL );           // Security Descriptor

    Status = LsaOpenPolicy( NULL,
                            &PolicyObjectAttributes,
                            POLICY_VIEW_LOCAL_INFORMATION,
                            &PolicyHandle );
    if ( NT_SUCCESS(Status) ) {

        //
        // Query the account domain information
        //

        Status = LsaQueryInformationPolicy( PolicyHandle,
                                            PolicyAccountDomainInformation,
                                            (PVOID *)PolicyAccountDomainInfo );
#if DBG
        if ( NT_SUCCESS(Status) ) {
            ASSERT( (*PolicyAccountDomainInfo) != NULL );
            ASSERT( (*PolicyAccountDomainInfo)->DomainSid != NULL );
            ASSERT( (*PolicyAccountDomainInfo)->DomainName.Buffer != NULL );
        }
#endif \\DBG

        //
        // Query the Primary domain information
        //

        Status = LsaQueryInformationPolicy( PolicyHandle,
                                            PolicyPrimaryDomainInformation,
                                            (PVOID *)PolicyPrimaryDomainInfo );
#if DBG
        if ( NT_SUCCESS(Status) ) {
            ASSERT( (*PolicyPrimaryDomainInfo) != NULL );
            ASSERT( (*PolicyPrimaryDomainInfo)->Sid != NULL );
            ASSERT( (*PolicyPrimaryDomainInfo)->Name.Buffer != NULL );
        }
#endif \\DBG

        IgnoreStatus = LsaClose( PolicyHandle );
        ASSERT(NT_SUCCESS(IgnoreStatus));
    }

    return(Status);
}




PSID
CreateUserSid(
    PSID    DomainSid,
    ULONG   Rid
    )

/*++

Routine Description:

    This function creates a domain account sid given a domain sid and
    the relative id of the account within the domain.

Arguments:

    None.

Return Value:

    Pointer to Sid, or NULL on failure.
    The returned Sid must be freed with DeleteUserSid

--*/
{

    NTSTATUS IgnoreStatus;
    PSID AccountSid;
    UCHAR AccountSubAuthorityCount = *RtlSubAuthorityCountSid(DomainSid) + (UCHAR)1;
    ULONG AccountSidLength = RtlLengthRequiredSid(AccountSubAuthorityCount);
    PULONG  RidLocation;

    // Temp sanity check
    ASSERT(AccountSidLength == SeLengthSid(DomainSid) + sizeof(ULONG));

    //
    // Allocate space for the account sid
    //

    AccountSid = MIDL_user_allocate(AccountSidLength);

    if (AccountSid != NULL) {

        //
        // Copy the domain sid into the first part of the account sid
        //

        IgnoreStatus = RtlCopySid(AccountSidLength, AccountSid, DomainSid);
        ASSERT(NT_SUCCESS(IgnoreStatus));

        //
        // Increment the account sid sub-authority count
        //

        *RtlSubAuthorityCountSid(AccountSid) = AccountSubAuthorityCount;

        //
        // Add the rid as the final sub-authority
        //

        RidLocation = RtlSubAuthoritySid(AccountSid, AccountSubAuthorityCount - 1);
        *RidLocation = Rid;
    }

    return(AccountSid);
}



VOID
DeleteUserSid(
    PSID    UserSid
    )

/*++

Routine Description:

    Frees a sid returned by CreateUserSid.

Arguments:

    None.

Return Value:

    None.

--*/
{
    MIDL_user_free(UserSid);
}



BOOLEAN
EnableSecurityPrivilege(
    VOID
    )

/*++

Routine Description:

    This function enabled the SeSecurityPrivilege privilege.

Arguments:

    None.

Return Value:

    TRUE  if privilege successfully enabled.
    FALSE if not successfully enabled.

--*/
{

    NTSTATUS Status;
    HANDLE Token;
    LUID SecurityPrivilege;
    PTOKEN_PRIVILEGES NewState;
    ULONG ReturnLength;


    //
    // Open our own token
    //

    Status = NtOpenProcessToken(
                 NtCurrentProcess(),
                 TOKEN_ADJUST_PRIVILEGES,
                 &Token
                 );
    if (!NT_SUCCESS(Status)) {
        printf(" \n\n\n");
        printf("Tsamobj: Can't open process token to enable Security Privilege.\n");
        printf("         Completion status of NtOpenProcessToken() is: 0x%lx\n", Status);
        printf("\n");
        return(FALSE);
    }


    //
    // Initialize the adjustment structure
    //

    SecurityPrivilege =
        RtlConvertLongToLargeInteger(SE_SECURITY_PRIVILEGE);

    ASSERT( (sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)) < 100);
    NewState = RtlAllocateHeap( RtlProcessHeap(), 0, 100 );

    NewState->PrivilegeCount = 1;
    NewState->Privileges[0].Luid = SecurityPrivilege;
    NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;


    //
    // Set the state of the privilege to ENABLED.
    //

    Status = NtAdjustPrivilegesToken(
                 Token,                            // TokenHandle
                 FALSE,                            // DisableAllPrivileges
                 NewState,                         // NewState
                 0,                                // BufferLength
                 NULL,                             // PreviousState (OPTIONAL)
                 &ReturnLength                     // ReturnLength
                 );
    // don't use NT_SUCCESS here because STATUS_NOT_ALL_ASSIGNED is a success status
    if (Status != STATUS_SUCCESS) {
        return(FALSE);
    }


    //
    // Clean up some stuff before returning
    //

    RtlFreeHeap( RtlProcessHeap(), 0, NewState );
    Status = NtClose( Token );
    ASSERT(NT_SUCCESS(Status));


    return TRUE;

}



VOID
printfSid(
    PSID    Sid
    )

/*++

Routine Description:

    Prints a sid

Arguments:

    None.

Return Value:

    None.

--*/
{
    UCHAR   Buffer[128];
    UCHAR   String[128];
    UCHAR   i;
    ULONG   Tmp;
    PISID   iSid = (PISID)Sid;  // pointer to opaque structure
    PSID    NextSid = (PSID)Buffer;

    ASSERT(sizeof(Buffer) >= RtlLengthRequiredSid(1));

    {
        SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_WORLD_SID_AUTHORITY;
        RtlInitializeSid(NextSid, &SidAuthority, 1 );
        *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_WORLD_RID;
        if (RtlEqualSid(Sid, NextSid)) {
            printf("World");
            return;
        }
    }

    {
        SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_LOCAL_SID_AUTHORITY;
        RtlInitializeSid(NextSid, &SidAuthority, 1 );
        *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_LOCAL_RID;
        if (RtlEqualSid(Sid, NextSid)) {
            printf("Local");
            return;
        }
    }

    {
        SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_CREATOR_SID_AUTHORITY;
        RtlInitializeSid(NextSid, &SidAuthority, 1 );
        *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_CREATOR_OWNER_RID;
        if (RtlEqualSid(Sid, NextSid)) {
            printf("Creator");
            return;
        }
    }

    {
        SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
        RtlInitializeSid(NextSid, &SidAuthority, 1 );
        *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_DIALUP_RID;
        if (RtlEqualSid(Sid, NextSid)) {
            printf("Dialup");
            return;
        }
    }

    {
        SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
        RtlInitializeSid(NextSid, &SidAuthority, 1 );
        *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_NETWORK_RID;
        if (RtlEqualSid(Sid, NextSid)) {
            printf("Network");
            return;
        }
    }

    {
        SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
        RtlInitializeSid(NextSid, &SidAuthority, 1 );
        *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_BATCH_RID;
        if (RtlEqualSid(Sid, NextSid)) {
            printf("Batch");
            return;
        }
    }

    {
        SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
        RtlInitializeSid(NextSid, &SidAuthority, 1 );
        *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_INTERACTIVE_RID;
        if (RtlEqualSid(Sid, NextSid)) {
            printf("Interactive");
            return;
        }
    }


    {
        SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
        RtlInitializeSid(NextSid, &SidAuthority, 1 );
        *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_LOCAL_SYSTEM_RID;
        if (RtlEqualSid(Sid, NextSid)) {
            printf("Local System");
            return;
        }
    }



    sprintf(Buffer, "S-%u-", (USHORT)iSid->Revision );
    strcpy(String, Buffer);

    if (  (iSid->IdentifierAuthority.Value[0] != 0)  ||
          (iSid->IdentifierAuthority.Value[1] != 0)     ){
        sprintf(Buffer, "0x%02hx%02hx%02hx%02hx%02hx%02hx",
                    (USHORT)iSid->IdentifierAuthority.Value[0],
                    (USHORT)iSid->IdentifierAuthority.Value[1],
                    (USHORT)iSid->IdentifierAuthority.Value[2],
                    (USHORT)iSid->IdentifierAuthority.Value[3],
                    (USHORT)iSid->IdentifierAuthority.Value[4],
                    (USHORT)iSid->IdentifierAuthority.Value[5] );
        strcat(String, Buffer);
    } else {
        Tmp = (ULONG)iSid->IdentifierAuthority.Value[5]          +
              (ULONG)(iSid->IdentifierAuthority.Value[4] <<  8)  +
              (ULONG)(iSid->IdentifierAuthority.Value[3] << 16)  +
              (ULONG)(iSid->IdentifierAuthority.Value[2] << 24);
        sprintf(Buffer, "%lu", Tmp);
        strcat(String, Buffer);
    }


    for (i=0;i<iSid->SubAuthorityCount ;i++ ) {
        sprintf(Buffer, "-%lu", iSid->SubAuthority[i]);
        strcat(String, Buffer);
    }

    printf(Buffer);

    return;
}


VOID
DetermineTestsToRun(
    VOID
    )

/*++

Routine Description:

    This function determines which tests are to be run.


Arguments:

    None.

Return Value:

    None.


--*/
{

    NTSTATUS            Status;
    HANDLE              Token;

    PTOKEN_USER         User;
    PTOKEN_GROUPS       Groups;

    ULONG               ReturnLength,
                        i;



    //
    // See if we can play with auditing information
    //

    SecurityOperatorTest = EnableSecurityPrivilege();


    //
    // Open our own token
    //

    Status = NtOpenProcessToken(
                 NtCurrentProcess(),
                 TOKEN_QUERY,
                 &Token
                 );
    if (!NT_SUCCESS(Status)) {
        printf(" \n\n\n");
        printf("Tsamobj: Can't open process token to query owner.\n");
        printf("         Completion status of NtOpenProcessToken() is: 0x%lx\n", Status);
        printf("\n");
        return;
    }


    //
    // Query the user id
    //

    User   = RtlAllocateHeap( RtlProcessHeap(), 0, 1000 ); // should be plenty big
    Status = NtQueryInformationToken( Token, TokenUser, User, 1000, &ReturnLength );
    ASSERT(NT_SUCCESS(Status));

    //
    // See if the ID is one of the special IDs (e.g., local admin,
    // domain account operator, or domain admin)
    //

    SeeIfSidIsSpecial( User->User.Sid );



    //
    // Query the group ids
    //

    Groups = RtlAllocateHeap( RtlProcessHeap(), 0, 1000 ); // should be plenty big
    Status = NtQueryInformationToken( Token, TokenGroups, Groups, 1000, &ReturnLength );
    ASSERT(NT_SUCCESS(Status));

    //
    // See if any of these IDs are special IDs
    //

    for (i=0; i<Groups->GroupCount; i++) {
        SeeIfSidIsSpecial( Groups->Groups[i].Sid );
    }





    //
    // Clean up some stuff before returning
    //

    RtlFreeHeap( RtlProcessHeap(), 0, User );
    RtlFreeHeap( RtlProcessHeap(), 0, Groups );
    Status = NtClose( Token );
    ASSERT(NT_SUCCESS(Status));



    printf("\n\n\n\nPerforming:\n\n");

    printf("        Administrator Alias Test. . . . . ");
    if (AdminsAliasTest) {
        printf("Yes\n\n");
    } else {
        printf("No\n\n");
    }

    printf("        Account Operator Alias  Test  . . ");
    if (AccountOpAliasTest) {
        printf("Yes\n\n");
    } else {
        printf("No\n\n");
    }

    printf("        Security Operator  Test . . . . . ");
    if (SecurityOperatorTest) {
        printf("Yes\n\n");
    } else {
        printf("No\n\n");
    }

    printf("\n\n\n");



    return;

}


VOID
SeeIfSidIsSpecial(
    IN PSID Sid
    )

/*++

Routine Description:

    This function determines whether the passed SID is one of the special
    SIDs, such as ADMINISTRATORS alias, or DomainAccountOperator, and
    sets test flags accordingly.


Arguments:

    Sid - Pointer to the SID to check.

Return Value:

    None.


--*/
{




    if (RtlEqualSid( Sid, AdminsAliasSid )){
        AdminsAliasTest = TRUE;
    }

    if (RtlEqualSid( Sid, AccountAliasSid )){
        AccountOpAliasTest = TRUE;
    }

    return;

}


///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Server Object Test Suite                                                  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////


BOOLEAN
ServerTestSuite(
    PHANDLE ServerHandle,
    PHANDLE DomainHandle,
    PHANDLE BuiltinDomainHandle,
    PSID    *DomainSid
    )

{
    NTSTATUS                        NtStatus;
    OBJECT_ATTRIBUTES               ObjectAttributes;
    BOOLEAN                         TestStatus = TRUE;
    ULONG                           CountReturned;
    SAM_ENUMERATE_HANDLE            EnumerationContext;
    PSAM_RID_ENUMERATION            EnumerationBuffer;
    PSID                            BuiltinDomainSid;
    ACCESS_MASK                     ServerAccessMask, DomainAccessMask;





    printf("\n");
    printf("\n");
    printf("  Server Object                                           Test\n");

    ///////////////////////////////////////////////////////////////////////////
    //                                                                       //
    // Connect To Server                                                     //
    //                                                                       //
    ///////////////////////////////////////////////////////////////////////////

    printf("\n");
    printf("    Connect / Disconnect. . . . . . . . . . . . . . . . .   Suite\n");

    printf("      Connect . . . . . . . . . . . . . . . . . . . . . .     ");


    ServerAccessMask = SAM_SERVER_READ | SAM_SERVER_EXECUTE;
    if (AdminsAliasTest) {
        ServerAccessMask |= SAM_SERVER_ALL_ACCESS;
    }
    if (SecurityOperatorTest) {
        ServerAccessMask |= ACCESS_SYSTEM_SECURITY;
    }

    InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL );


    NtStatus = SamConnect(
                  NULL,                     // ServerName (Local machine)
                  ServerHandle,
                  ServerAccessMask,
                  &ObjectAttributes
                  );


    if (!NT_SUCCESS(NtStatus)) {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    } else {
        printf("Succeeded\n");
    }


    if (NT_SUCCESS(NtStatus)) {

        printf("      Disconnect  . . . . . . . . . . . . . . . . . . . .     ");

        NtStatus = SamCloseHandle( (*ServerHandle) );

        if (!NT_SUCCESS(NtStatus)) {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        } else {
            printf("Succeeded\n");
        }
    }



    printf("      Re-Connect  . . . . . . . . . . . . . . . . . . . .     ");


    NtStatus = SamConnect(
                  NULL,                     // ServerName (Local machine)
                  ServerHandle,
                  ServerAccessMask,
                  &ObjectAttributes
                  );


    if (!NT_SUCCESS(NtStatus)) {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    } else {
        printf("Succeeded\n");
    }


    ///////////////////////////////////////////////////////////////////////////
    //                                                                       //
    // Lookup/Enumerate Domains Suite                                        //
    //                                                                       //
    ///////////////////////////////////////////////////////////////////////////


    printf("\n");
    printf("    Domain Lookup/Enumerate/Open  . . . . . . . . . . . .   Suite\n");



    if (NT_SUCCESS(NtStatus)) {

        printf("      Lookup Account Domain . . . . . . . . . . . . . . .     ");


        NtStatus = SamLookupDomainInSamServer(
                       (*ServerHandle),
                       &AccountDomainName,
                       DomainSid
                       );

        if (!NT_SUCCESS(NtStatus)) {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        } else {
            if ( TRUE != RtlEqualSid((*DomainSid), AccountDomainSid)) {
                printf("Failed\n");
                printf("        The SID retrieved from the policy database did not\n");
                printf("        match the SID retrieved from SAM for the account\n");
                printf("        domain.\n");
                printf("        Sid from Policy Database is: ");
                printfSid(      AccountDomainSid ); printf("\n");
                printf("        Sid from SAM is: ");
                printfSid(      (*DomainSid) ); printf("\n");
                TestStatus = FALSE;
            } else {
                printf("Succeeded\n");
            }
        }

    }






    if (NT_SUCCESS(NtStatus)) {

        printf("      Enumerate Domain  . . . . . . . . . . . . . . . . .     ");


        EnumerationContext = 0;
        EnumerationBuffer = NULL;
        NtStatus = SamEnumerateDomainsInSamServer(
                       (*ServerHandle),
                       &EnumerationContext,
                       (PVOID *)&EnumerationBuffer,
                       1024,                        // PreferedMaximumLength
                       &CountReturned
                       );

        if (!NT_SUCCESS(NtStatus)) {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        } else {

            if (CountReturned == 0) {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                printf("        CountReturned is: 0x%lx\n", CountReturned);
                printf("        EnumerationContext is: 0x%lx\n", EnumerationContext);
                printf("        EnumerationBuffer Address is: 0x%lx\n", (ULONG)EnumerationBuffer);
                TestStatus = FALSE;

            } else {
                printf("Succeeded\n");
            }

            SamFreeMemory( EnumerationBuffer );
        }

    }






    if (NT_SUCCESS(NtStatus)) {

        printf("      Open Account Domain . . . . . . . . . . . . . . . .     ");

        if (NT_SUCCESS(NtStatus)) {

            DomainAccessMask = DOMAIN_READ | DOMAIN_EXECUTE;
            if (AccountOpAliasTest) {
                DomainAccessMask |= DOMAIN_READ | DOMAIN_WRITE | DOMAIN_EXECUTE;
            }
            if (AdminsAliasTest) {
                DomainAccessMask |= DOMAIN_ALL_ACCESS;
            }
            if (SecurityOperatorTest) {
                DomainAccessMask |= ACCESS_SYSTEM_SECURITY;
            }
            NtStatus = SamOpenDomain(
                           (*ServerHandle),
                           DomainAccessMask,
                           *DomainSid,
                           DomainHandle
                           );

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            } else {
                printf("Succeeded\n");
            }
        }

    }

    if (NT_SUCCESS(NtStatus)) {

        printf("      Open Builtin Domain . . . . . . . . . . . . . . . .     ");

        NtStatus = SamLookupDomainInSamServer(
                       (*ServerHandle),
                       &BuiltinDomainName,
                       &BuiltinDomainSid
                       );

        if (NT_SUCCESS(NtStatus)) {

            DomainAccessMask = DOMAIN_READ | DOMAIN_EXECUTE;
            if (AccountOpAliasTest) {
                DomainAccessMask |= DOMAIN_READ | DOMAIN_WRITE | DOMAIN_EXECUTE;
            }
            if (AdminsAliasTest) {
                DomainAccessMask |= (DOMAIN_EXECUTE | DOMAIN_READ |
                                     DOMAIN_READ_OTHER_PARAMETERS |
                                     DOMAIN_ADMINISTER_SERVER     |
                                     DOMAIN_CREATE_ALIAS);
            }
//            if (SecurityOperatorTest) {
//                DomainAccessMask |= ACCESS_SYSTEM_SECURITY;
//            }
            NtStatus = SamOpenDomain(
                           (*ServerHandle),
                           DomainAccessMask,
                           BuiltinDomainSid,
                           BuiltinDomainHandle
                           );

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            } else {
                printf("Succeeded\n");
            }
        }

    }

    return(TestStatus);


}


///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Security Manipulation Test Suite                                          //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////


BOOLEAN
SecurityTestSuite(
    HANDLE ServerHandle,
    HANDLE DomainHandle,
    ULONG Pass
    )
{

    BOOLEAN                 TestStatus = TRUE;
    NTSTATUS                NtStatus;

    PSECURITY_DESCRIPTOR    OriginalServerSD,
                            OriginalDomainSD,
                            OriginalUserSD,
                            OriginalGroupSD,
                            SD1;

    SECURITY_INFORMATION    SI1;
    PVOID TmpPointer1;

    SECURITY_DESCRIPTOR     SD1_Body;

    HANDLE                  GroupHandle,
                            UserHandle;




    printf("\n");
    printf("\n");
    printf("\n");

    if (Pass == 1) {

        printf("  Security Manipulation (Pass #1)                         Test\n");

        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Query Suite                                                           //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Query Security  . . . . . . . . . . . . . . . . . . .   Suite\n");


        //
        // Get Server's original SD
        //


        SI1 = 0;
        if (AdminsAliasTest) {
            SI1 |= OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
                   DACL_SECURITY_INFORMATION;
        }
        if (SecurityOperatorTest) {
            SI1 |= SACL_SECURITY_INFORMATION;
        }
        if (SI1 != 0) {
            printf("      Query Server Security Descriptor  . . . . . . . . . .     ");
            SD1 = NULL;
            NtStatus = SamQuerySecurityObject(
                           ServerHandle,
                           SI1,
                           &SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                TestStatus = CheckReturnedSD( SI1, SD1, TRUE );

                //
                // Normally we would do a "SamFreeMemory( SD1 )" here.
                // However, we want to save this SD for future reference
                // and use.
                //

                OriginalServerSD = SD1;

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
        }





        //
        // Get domain's original SD
        //


        SI1 = 0;
        if (AdminsAliasTest) {
            SI1 |= OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
                   DACL_SECURITY_INFORMATION;
        }
        if (SecurityOperatorTest) {
            SI1 |= SACL_SECURITY_INFORMATION;
        }
        if (SI1 != 0) {
            printf("      Query Domain Security Descriptor  . . . . . . . . . .     ");
            SD1 = NULL;
            NtStatus = SamQuerySecurityObject(
                           DomainHandle,
                           SI1,
                           &SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                TestStatus = CheckReturnedSD( SI1, SD1, TRUE );

                //
                // Normally we would do a "SamFreeMemory( SD1 )" here.
                // However, we want to save this SD for future reference
                // and use.
                //

                OriginalDomainSD = SD1;

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
        }






        //
        // Make sure the wrapper doesn't choke on a non-null pointer being passed
        // (assuming we have allocated memory).
        //


        SI1 = 0;
        if (AdminsAliasTest) {
            SI1 |= OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
                   DACL_SECURITY_INFORMATION;
        }
        if (SecurityOperatorTest) {
            SI1 |= SACL_SECURITY_INFORMATION;
        }
        if (SI1 != 0) {
            printf("      Query Passing Non-null return buffer  . . . . . . . .     ");
            SD1 = RtlAllocateHeap( RtlProcessHeap(), 0, 1000 ); ASSERT(SD1 != NULL);
            TmpPointer1 = SD1;
            NtStatus = SamQuerySecurityObject(
                           DomainHandle,
                           SI1,
                           &SD1
                           );
            if (NT_SUCCESS(NtStatus)) {
                if (SD1 != TmpPointer1) {

                    TestStatus = CheckReturnedSD( SI1, SD1, TRUE );
                    if (TestStatus) {
                        SamFreeMemory( SD1 );
                    }


                } else {
                    printf("Failed\n");
                    printf("        Passed buffer address used on return.\n");
                    printf("        RPC should have allocated another buffer.\n");
                    TestStatus = FALSE;
                }
            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }


            RtlFreeHeap( RtlProcessHeap(), 0, TmpPointer1 );

        }






        //
        // Make sure we can query nothing
        //

        printf("      Query Nothing . . . . . . . . . . . . . . . . . . . .     ");

        SI1 = 0;
        SD1 = NULL;
        NtStatus = SamQuerySecurityObject(
                       DomainHandle,
                       SI1,
                       &SD1
                       );
        if (NT_SUCCESS(NtStatus)) {

            TestStatus = CheckReturnedSD( SI1, SD1, TRUE );
            if (TestStatus) {
                SamFreeMemory( SD1 );
            }

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }





        //
        // Query owner
        //


        if (AdminsAliasTest) {
            printf("      Query Owner (Server Object) . . . . . . . . . . . . .     ");
            SI1 = OWNER_SECURITY_INFORMATION;
            SD1 = NULL;
            NtStatus = SamQuerySecurityObject(
                           ServerHandle,
                           SI1,
                           &SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                TestStatus = CheckReturnedSD( SI1, SD1, TRUE );
                if (TestStatus) {
                    SamFreeMemory( SD1 );
                }

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
        }




        if (AdminsAliasTest) {
            printf("      Query Owner (Domain Object) . . . . . . . . . . . . .     ");
            SI1 = OWNER_SECURITY_INFORMATION;
            SD1 = NULL;
            NtStatus = SamQuerySecurityObject(
                           DomainHandle,
                           SI1,
                           &SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                TestStatus = CheckReturnedSD( SI1, SD1, TRUE );
                if (TestStatus) {
                    SamFreeMemory( SD1 );
                }

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
        }





        if (AdminsAliasTest) {

            //
            // Query Group
            //

            printf("      Query Group . . . . . . . . . . . . . . . . . . . . .     ");

            SI1 = GROUP_SECURITY_INFORMATION;
            SD1 = NULL;
            NtStatus = SamQuerySecurityObject(
                           DomainHandle,
                           SI1,
                           &SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                TestStatus = CheckReturnedSD( SI1, SD1, TRUE );
                if (TestStatus) {
                    SamFreeMemory( SD1 );
                }

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }





            //
            // Query Dacl
            //

            printf("      Query DACL  . . . . . . . . . . . . . . . . . . . . .     ");

            SI1 = DACL_SECURITY_INFORMATION;
            SD1 = NULL;
            NtStatus = SamQuerySecurityObject(
                           DomainHandle,
                           SI1,
                           &SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                TestStatus = CheckReturnedSD( SI1, SD1, TRUE );
                if (TestStatus) {
                    SamFreeMemory( SD1 );
                }

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }





            //
            // Query Sacl
            //

            printf("      Query SACL  . . . . . . . . . . . . . . . . . . . . .     ");

            SI1 = SACL_SECURITY_INFORMATION;
            SD1 = NULL;
            NtStatus = SamQuerySecurityObject(
                           DomainHandle,
                           SI1,
                           &SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                TestStatus = CheckReturnedSD( SI1, SD1, TRUE );
                if (TestStatus) {
                    SamFreeMemory( SD1 );
                }

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }

        }  // end_if (AdminsAliasTest)





        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Set Suite                                                             //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Set Security  . . . . . . . . . . . . . . . . . . . .   Suite\n");


        //
        // Make sure we can set nothing
        //

        printf("      Set Nothing . . . . . . . . . . . . . . . . . . . . .     ");

        SI1 = 0;
        SD1 = &SD1_Body;
        NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
        ASSERT( NT_SUCCESS(NtStatus) );
        NtStatus = SamSetSecurityObject(
                       DomainHandle,
                       SI1,     // <------ This is invalid
                       SD1
                       );
        if (NtStatus == STATUS_INVALID_PARAMETER) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }






        //
        // set something not passed
        //

        printf("      Set something not passed. . . . . . . . . . . . . . .     ");

        SI1 = GROUP_SECURITY_INFORMATION;
        SD1 = &SD1_Body;
        NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
        ASSERT( NT_SUCCESS(NtStatus) );
        NtStatus = SamSetSecurityObject(
                       DomainHandle,
                       SI1,
                       SD1
                       );
        if (NtStatus == STATUS_BAD_DESCRIPTOR_FORMAT) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }






        //
        // set a non-existant DACL
        //

        if (AdminsAliasTest) {
            printf("      Set non-existant DACL (Server object) . . . . . . . .     ");

            SI1 = DACL_SECURITY_INFORMATION;
            SD1 = &SD1_Body;
            NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
            SD1_Body.Control = SE_DACL_PRESENT;
            ASSERT( NT_SUCCESS(NtStatus) );
            NtStatus = SamSetSecurityObject(
                           ServerHandle,
                           SI1,
                           SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
        }



        if (AdminsAliasTest) {
            printf("      Set non-existant DACL (Domain Object) . . . . . . . .     ");

            SI1 = DACL_SECURITY_INFORMATION;
            SD1 = &SD1_Body;
            NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
            SD1_Body.Control = SE_DACL_PRESENT;
            ASSERT( NT_SUCCESS(NtStatus) );
            NtStatus = SamSetSecurityObject(
                           DomainHandle,
                           SI1,
                           SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
        }





        //
        // set original DACL (From original SD)
        //

        if (AdminsAliasTest) {

            printf("      Set original DACL (Server Object) . . . . . . . . . .     ");

            SI1 = DACL_SECURITY_INFORMATION;
            SD1 = OriginalServerSD;
            NtStatus = SamSetSecurityObject(
                           ServerHandle,
                           SI1,
                           SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
        }



        if (AdminsAliasTest) {

            printf("      Set original DACL (Domain Object) . . . . . . . . . .     ");

            SI1 = DACL_SECURITY_INFORMATION;
            SD1 = OriginalDomainSD;
            NtStatus = SamSetSecurityObject(
                           DomainHandle,
                           SI1,
                           SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
        }





        if (AdminsAliasTest) {

            //
            // set a non-existant SACL
            //

            printf("      Set non-existant SACL . . . . . . . . . . . . . . . .     ");

            SI1 = SACL_SECURITY_INFORMATION;
            SD1 = &SD1_Body;
            NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
            SD1_Body.Control = SE_SACL_PRESENT;
            ASSERT( NT_SUCCESS(NtStatus) );
            NtStatus = SamSetSecurityObject(
                           DomainHandle,
                           SI1,
                           SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }






            //
            // set original SACL (From original SD)
            //

            printf("      Set original SACL . . . . . . . . . . . . . . . . . .     ");

            SI1 = SACL_SECURITY_INFORMATION;
            SD1 = OriginalDomainSD;
            NtStatus = SamSetSecurityObject(
                           DomainHandle,
                           SI1,
                           SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }





            //
            // set a owner to null
            //

            printf("      Set null Owner  . . . . . . . . . . . . . . . . . . .     ");

            SI1 = OWNER_SECURITY_INFORMATION;
            SD1 = &SD1_Body;
            NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
            SD1_Body.Owner = NULL;
            ASSERT( NT_SUCCESS(NtStatus) );
            NtStatus = SamSetSecurityObject(
                           DomainHandle,
                           SI1,
                           SD1
                           );
            if (NtStatus = STATUS_BAD_DESCRIPTOR_FORMAT) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }





            //
            // set owner to invalid value
            //

            printf("      Set owner to invalid value  . . . . . . . . . . . . .     ");

            SI1 = OWNER_SECURITY_INFORMATION;
            SD1 = &SD1_Body;
            NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
            SD1_Body.Owner = WorldSid;
            ASSERT( NT_SUCCESS(NtStatus) );
            NtStatus = SamSetSecurityObject(
                           DomainHandle,
                           SI1,
                           SD1
                           );
            if (NtStatus = STATUS_INVALID_OWNER) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }




            //
            // set a owner to valid value
            //

            printf("      Set owner to valid value  . . . . . . . . . . . . . .     ");

            printf("Untested\n");





            //
            // set group to null
            //

            printf("      Set null Group  . . . . . . . . . . . . . . . . . . .     ");

            SI1 = GROUP_SECURITY_INFORMATION;
            SD1 = &SD1_Body;
            NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
            SD1_Body.Group = NULL;
            ASSERT( NT_SUCCESS(NtStatus) );
            NtStatus = SamSetSecurityObject(
                           DomainHandle,
                           SI1,
                           SD1
                           );
            if (NtStatus = STATUS_BAD_DESCRIPTOR_FORMAT) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }






            //
            // set Group to valid value
            //

            printf("      Set Group to valid value  . . . . . . . . . . . . . .     ");

            SI1 = GROUP_SECURITY_INFORMATION;
            SD1 = &SD1_Body;
            NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
            SD1_Body.Group = WorldSid;
            ASSERT( NT_SUCCESS(NtStatus) );
            NtStatus = SamSetSecurityObject(
                           DomainHandle,
                           SI1,
                           SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }





            //
            // set Group back to original value
            //

            printf("      Set Group to original value . . . . . . . . . . . . .     ");

            SI1 = GROUP_SECURITY_INFORMATION;
            SD1 = OriginalDomainSD;
            NtStatus = SamSetSecurityObject(
                           DomainHandle,
                           SI1,
                           SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
        }




    }   // end Pass1


    if (Pass == 2) {

        ACCESS_MASK         AccessMask;
        PSID_NAME_USE       LookedUpUses;
        PULONG              LookedUpRids;
        UNICODE_STRING      AccountNames[10];
        STRING              AccountNameAnsi;


        //
        // This pass depends upon user and group accounts established in pass #1
        //





        if (AdminsAliasTest) {


            printf("  Security Manipulation (Pass #2)                         Test\n");

            ///////////////////////////////////////////////////////////////////////////
            //                                                                       //
            // Query Suite                                                           //
            //                                                                       //
            ///////////////////////////////////////////////////////////////////////////

            printf("\n");
            printf("    Query Security (User Object). . . . . . . . . . . . .   Suite\n");


            AccessMask = READ_CONTROL;
            if (SecurityOperatorTest) {
                AccessMask |= ACCESS_SYSTEM_SECURITY;
            }

            //
            // Open the user created in pass #1
            //

            RtlInitString( &AccountNameAnsi, USER_NAME1 );
            NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
            TST_SUCCESS_ASSERT(NtStatus);

            NtStatus = SamLookupNamesInDomain(
                           DomainHandle,
                           1,
                           &AccountNames[0],
                           &LookedUpRids,
                           &LookedUpUses
                           );
            RtlFreeUnicodeString( &AccountNames[0] );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(LookedUpUses[0] == SidTypeUser);
            NtStatus = SamOpenUser(
                           DomainHandle,
                           AccessMask,
                           LookedUpRids[0],
                           &UserHandle);
            SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );
            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed to open user account created in pass #1\n");
            }
            TST_SUCCESS_ASSERT(NT_SUCCESS(NtStatus));



            //
            // Get user's original SD
            //

            SI1 |= OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
                   DACL_SECURITY_INFORMATION;
            if (SecurityOperatorTest) {
                SI1 |= SACL_SECURITY_INFORMATION;
            }

            printf("      Query User Security Descriptor  . . . . . . . . . . .     ");
            SD1 = NULL;
            NtStatus = SamQuerySecurityObject(
                           UserHandle,
                           SI1,
                           &SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                TestStatus = CheckReturnedSD( SI1, SD1, TRUE );

                //
                // Normally we would do a "SamFreeMemory( SD1 )" here.
                // However, we want to save this SD for future reference
                // and use.
                //

                OriginalUserSD = SD1;

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }





            NtStatus = SamCloseHandle( UserHandle );
            TST_SUCCESS_ASSERT( UserHandle );



            ///////////////////////////////////////////////////////////////////////////
            //                                                                       //
            // Set Suite                                                             //
            //                                                                       //
            ///////////////////////////////////////////////////////////////////////////

            printf("\n");
            printf("    Set Security  (User Object) . . . . . . . . . . . . .   Suite\n");

            AccessMask = WRITE_DAC | WRITE_OWNER;
            if (SecurityOperatorTest) {
                AccessMask |= ACCESS_SYSTEM_SECURITY;
            }

            //
            // Open the user created in pass #1
            //

            RtlInitString( &AccountNameAnsi, USER_NAME1 );
            NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
            TST_SUCCESS_ASSERT(NtStatus);

            NtStatus = SamLookupNamesInDomain(
                           DomainHandle,
                           1,
                           &AccountNames[0],
                           &LookedUpRids,
                           &LookedUpUses
                           );
            RtlFreeUnicodeString( &AccountNames[0] );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(LookedUpUses[0] == SidTypeUser);
            NtStatus = SamOpenUser(
                           DomainHandle,
                           AccessMask,
                           LookedUpRids[0],
                           &UserHandle);
            SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );
            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed to open user account created in pass #1\n");
            }
            TST_SUCCESS_ASSERT(NT_SUCCESS(NtStatus));


            //
            // Make sure we can set nothing
            //

            printf("      Set Nothing . . . . . . . . . . . . . . . . . . . . .     ");

            SI1 = 0;
            SD1 = &SD1_Body;
            NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
            ASSERT( NT_SUCCESS(NtStatus) );
            NtStatus = SamSetSecurityObject(
                           UserHandle,
                           SI1,     // <------ This is invalid
                           SD1
                           );
            if (NtStatus == STATUS_INVALID_PARAMETER) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }






            //
            // set something not passed
            //

            printf("      Set something not passed. . . . . . . . . . . . . . .     ");

            SI1 = GROUP_SECURITY_INFORMATION;
            SD1 = &SD1_Body;
            NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
            ASSERT( NT_SUCCESS(NtStatus) );
            NtStatus = SamSetSecurityObject(
                           UserHandle,
                           SI1,
                           SD1
                           );
            if (NtStatus == STATUS_BAD_DESCRIPTOR_FORMAT) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }








            printf("      Set non-existant DACL . . . . . . . . . . . . . . . .     ");

            SI1 = DACL_SECURITY_INFORMATION;
            SD1 = &SD1_Body;
            NtStatus = RtlCreateSecurityDescriptor( SD1, SECURITY_DESCRIPTOR_REVISION1 );
            SD1_Body.Control = SE_DACL_PRESENT;
            ASSERT( NT_SUCCESS(NtStatus) );
            NtStatus = SamSetSecurityObject(
                           UserHandle,
                           SI1,
                           SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }






            //
            // set original DACL (From original SD)
            //


            printf("      Set original DACL . . . . . . . . . . . . . . . . . .     ");

            SI1 = DACL_SECURITY_INFORMATION;
            SD1 = OriginalUserSD;
            NtStatus = SamSetSecurityObject(
                           UserHandle,
                           SI1,
                           SD1
                           );
            if (NT_SUCCESS(NtStatus)) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }







            NtStatus = SamCloseHandle( UserHandle );
            TST_SUCCESS_ASSERT( UserHandle );



        }

        DBG_UNREFERENCED_LOCAL_VARIABLE( GroupHandle );
        DBG_UNREFERENCED_LOCAL_VARIABLE( OriginalGroupSD );
    }





    return TestStatus;
}


BOOLEAN
CheckReturnedSD(
    IN SECURITY_INFORMATION SI,
    IN PSECURITY_DESCRIPTOR SD,
    IN BOOLEAN              PrintTestSuccess
    )


{
    NTSTATUS NtStatus;

    BOOLEAN  Failed = FALSE,
             IgnoreBoolean,
             AclPresent,
             TestStatus = TRUE;

    PSID     SID;
    PACL     ACL;



    //
    // Check a returned security descriptor agains the information requested.
    //

    if (SD == NULL) {
        TestStatus = FALSE;
        if (PrintTestSuccess) {
            printf("Failed\n");
            Failed = TRUE;
            printf("        The SecurityDescriptor return address was not properly\n");
            printf("        set.\n");
        }
    }


    if (TestStatus) {

        //
        // Check owner
        //

        NtStatus = RtlGetOwnerSecurityDescriptor ( SD, &SID, &IgnoreBoolean);
        ASSERT(NT_SUCCESS(NtStatus));
        if (SI & OWNER_SECURITY_INFORMATION) {
            if (SID == NULL) {
                if (PrintTestSuccess) {
                    if (!Failed) {
                        printf("Failed\n");
                        printf("        Security descriptor address is 0x%lx\n", SD );
                        Failed = TRUE;
                    }
                    printf("        An owner was requested but the owner field of the\n");
                    printf("        security descriptor is not set.\n");
                    TestStatus = FALSE;

                }
            }
        } else {    // Owner not specified
            if (SID != NULL) {
                if (PrintTestSuccess) {
                    if (!Failed) {
                        printf("Failed\n");
                        printf("        Security descriptor address is 0x%lx\n", SD );
                        Failed = TRUE;
                    }
                    printf("        An owner was not requested but the owner field of the\n");
                    printf("        security descriptor is set.\n");
                    TestStatus = FALSE;
                }
            }
        }




        //
        // Check group
        //

        NtStatus = RtlGetGroupSecurityDescriptor ( SD, &SID, &IgnoreBoolean);
        ASSERT(NT_SUCCESS(NtStatus));
        if (SI & GROUP_SECURITY_INFORMATION) {
            if (SID == NULL) {
                if (PrintTestSuccess) {
                    if (!Failed) {
                        printf("Failed\n");
                        printf("        Security descriptor address is 0x%lx\n", SD );
                        Failed = TRUE;
                    }
                    printf("        A group was requested but the group field of the\n");
                    printf("        security descriptor is not set.\n");
                    TestStatus = FALSE;

                }
            }
        } else {    // Group not specified
            if (SID != NULL) {
                if (PrintTestSuccess) {
                    if (!Failed) {
                        printf("Failed\n");
                        printf("        Security descriptor address is 0x%lx\n", SD );
                        Failed = TRUE;
                    }
                    printf("        A group was not requested but the group field of the\n");
                    printf("        security descriptor is set.\n");
                    TestStatus = FALSE;
                }
            }
        }




        //
        // Check sacl
        //

        NtStatus = RtlGetSaclSecurityDescriptor ( SD, &AclPresent, &ACL, &IgnoreBoolean);
        ASSERT(NT_SUCCESS(NtStatus));
        if (SI & SACL_SECURITY_INFORMATION) {
            if (!AclPresent) {
                if (PrintTestSuccess) {
                    if (!Failed) {
                        printf("Failed\n");
                        printf("        Security descriptor address is 0x%lx\n", SD );
                        Failed = TRUE;
                    }
                    printf("        An SACL was requested but the SaclPresent flag\n");
                    printf("        of the security descriptor is not set.\n");
                    TestStatus = FALSE;

                }
            }
        } else {    // sacl not specified
            if (AclPresent) {
                if (PrintTestSuccess) {
                    if (!Failed) {
                        printf("Failed\n");
                        printf("        Security descriptor address is 0x%lx\n", SD );
                        Failed = TRUE;
                    }
                    printf("        An SACL was not requested but the SaclPresent flag\n");
                    printf("        of the security descriptor is set.\n");
                    TestStatus = FALSE;
                }
            }
        }





        //
        // Check Dacl
        //

        NtStatus = RtlGetDaclSecurityDescriptor ( SD, &AclPresent, &ACL, &IgnoreBoolean);
        ASSERT(NT_SUCCESS(NtStatus));
        if (SI & DACL_SECURITY_INFORMATION) {
            if (!AclPresent) {
                if (PrintTestSuccess) {
                    if (!Failed) {
                        printf("Failed\n");
                        printf("        Security descriptor address is 0x%lx\n", SD );
                        Failed = TRUE;
                    }
                    printf("        A DACL was requested but the DaclPresent flag\n");
                    printf("        of the security descriptor is not set.\n");
                    TestStatus = FALSE;

                }
            }
        } else {    // Dacl not specified
            if (AclPresent) {
                if (PrintTestSuccess) {
                    if (!Failed) {
                        printf("Failed\n");
                        printf("        Security descriptor address is 0x%lx\n", SD );
                        Failed = TRUE;
                    }
                    printf("        A DACL was not requested but the DaclPresent flag\n");
                    printf("        of the security descriptor is set.\n");
                    TestStatus = FALSE;
                }
            }
        }





    }




    if (PrintTestSuccess) {
        if (TestStatus) {
            printf("Succeeded\n");
        }
    }



    return(TestStatus);
}


///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Domain Object Test Suite                                                  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////


BOOLEAN
DomainTestSuite(
    HANDLE DomainHandle
    )
{

    BOOLEAN  TestStatus = TRUE;
    NTSTATUS NtStatus, IgnoreStatus;
    PVOID    Buffer, Buffer1, Buffer2;
    CHAR     UnusedBuffer[20];
    UNICODE_STRING      AccountName;
    STRING              AccountNameAnsi;
    HANDLE GroupHandle = NULL;
    HANDLE AliasHandle = NULL;
    HANDLE UserHandle = NULL;
    HANDLE ValidUserHandle = NULL;
    ULONG  GroupRid, AliasRid, UserRid, SavedGroupRid, SavedAliasRid, AccountCount, i;
    SAM_ENUMERATE_HANDLE EnumerationContext;
    ULONG   CountReturned;
    USHORT NameLength;
    PUNICODE_STRING  LookedUpNames;
    PSID_NAME_USE    LookedUpUses;
    PULONG           LookedUpRids;


    printf("\n");
    printf("\n");
    printf("\n");
    printf("  Domain                                                  Test\n");

    ///////////////////////////////////////////////////////////////////////////
    //                                                                       //
    // Query Suite                                                           //
    //                                                                       //
    ///////////////////////////////////////////////////////////////////////////

    printf("\n");
    printf("    Query Information . . . . . . . . . . . . . . . . . .   Suite\n");


    //
    // Make sure the wrapper doesn't choke on a non-null pointer being passed
    // (assuming we have allocated memory).
    //

    printf("      Query Buffer Allocation Test  . . . . . . . . . . . .     ");

    Buffer = &UnusedBuffer[0];
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainStateInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != &UnusedBuffer[0]) {
            if (Buffer != NULL) {
                printf("Succeeded\n");
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Passed buffer address used on return.\n");
            printf("        RPC should have allocated another buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }


    //
    // Query all the fixed length info levels
    //  Query - Password, Logoff, ServerRole, DomainState, ModifiedCount, LockoutInfo
    //

    printf("      Query DomainState . . . . . . . . . . . . . . . . . .     ");

    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainStateInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
                printf("Succeeded\n");
                SamFreeMemory( Buffer );
        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;

    }


    printf("      Query ServerRole  . . . . . . . . . . . . . . . . . .     ");
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainServerRoleInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
                printf("Succeeded\n");
                SamFreeMemory( Buffer );
        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;

    }


    printf("      Query Password Information  . . . . . . . . . . . . .     ");
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainPasswordInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
                printf("Succeeded\n");
                SamFreeMemory( Buffer );
        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;

    }


    printf("      Query Logoff Information  . . . . . . . . . . . . . .     ");
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainLogoffInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
                printf("Succeeded\n");
                SamFreeMemory( Buffer );
        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;

    }


    printf("      Query Modified  . . . . . . . . . . . . . . . . . . .     ");
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainModifiedInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
                printf("Succeeded\n");
                SamFreeMemory( Buffer );
        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;

    }


    printf("      Query Lockout . . . . . . . . . . . . . . . . . . . .     ");
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainLockoutInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
                printf("Succeeded\n");
                SamFreeMemory( Buffer );
        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;

    }





    //
    // Query the name of the domain ...
    //

    printf("      Query Domain Name . . . . . . . . . . . . . . . . . .     ");

    Buffer = NULL;
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainNameInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
            if ( (((DOMAIN_NAME_INFORMATION *)Buffer)->DomainName.MaximumLength > 0) &&
                 (((DOMAIN_NAME_INFORMATION *)Buffer)->DomainName.Buffer != NULL) ) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        String body returned and allocated,\n");
                printf("        but character buffer pointer is NULL.\n");
                TestStatus = FALSE;
            }
            SamFreeMemory( Buffer );
        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }



    //
    // Query whatever is in the OEM Information field ...
    //

    printf("      Query OEM Information . . . . . . . . . . . . . . . .     ");

    Buffer = NULL;
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainOemInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
            if ( (((DOMAIN_OEM_INFORMATION *)Buffer)->OemInformation.MaximumLength >= 0) &&
                 (((DOMAIN_OEM_INFORMATION *)Buffer)->OemInformation.Buffer != NULL) ) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        String body returned and allocated,\n");
                printf("        but character buffer pointer is NULL.\n");
                TestStatus = FALSE;
            }
            SamFreeMemory( Buffer );
        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }



    //
    // Query whatever is in the Replication Information field ...
    //

    printf("      Query Replication Information . . . . . . . . . . . .     ");

    Buffer = NULL;
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainReplicationInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
            if ( (((DOMAIN_REPLICATION_INFORMATION *)Buffer)->ReplicaSourceNodeName.MaximumLength >= 0) &&
                 (((DOMAIN_REPLICATION_INFORMATION *)Buffer)->ReplicaSourceNodeName.Buffer != NULL) ) {

                printf("Succeeded\n");

            } else {
                printf("Failed\n");
                printf("        String body returned and allocated,\n");
                printf("        but character buffer pointer is NULL.\n");
                TestStatus = FALSE;
            }
            SamFreeMemory( Buffer );
        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }



    //
    // Query domain general Information...
    //

    printf("      Query General Information . . . . . . . . . . . . . .     ");

    Buffer = NULL;
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainGeneralInformation,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {

            printf("Succeeded\n");
            printf("          Number of Users  is: 0x%lx\n",
                 ((DOMAIN_GENERAL_INFORMATION *)Buffer)->UserCount );
            printf("          Number of groups is: 0x%lx\n",
                 ((DOMAIN_GENERAL_INFORMATION *)Buffer)->GroupCount);
            printf("          Number of aliases is: 0x%lx\n",
                 ((DOMAIN_GENERAL_INFORMATION *)Buffer)->AliasCount);


            SamFreeMemory( Buffer );

        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }



    //
    // Query domain general Information...
    //

    printf("      Query General Information 2 . . . . . . . . . . . . .     ");

    Buffer = NULL;
    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainGeneralInformation2,
                   &Buffer
                   );
    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {

            printf("Succeeded\n");
            printf("          Number of Users  is: 0x%lx\n",
                 ((DOMAIN_GENERAL_INFORMATION2 *)Buffer)->I1.UserCount );
            printf("          Number of groups is: 0x%lx\n",
                 ((DOMAIN_GENERAL_INFORMATION2 *)Buffer)->I1.GroupCount);
            printf("          Number of aliases is: 0x%lx\n",
                 ((DOMAIN_GENERAL_INFORMATION2 *)Buffer)->I1.AliasCount);


            SamFreeMemory( Buffer );

        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            TestStatus = FALSE;
        }
    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }








    ///////////////////////////////////////////////////////////////////////////
    //                                                                       //
    // Set Suite                                                             //
    //                                                                       //
    ///////////////////////////////////////////////////////////////////////////

    printf("    Set Information . . . . . . . . . . . . . . . . . . .   Suite\n");

    //
    // Set all the fixed length info levels
    //   - Password, Logoff, ServerRole, DomainState, ModifiedCount
    //

/*
 *  CANT TEST SERVER STATE SETTING WITHOUT BREAKING THE REST OF THE TEST.
 *  THE REASON IS, ONCE THE STATE IS CHANGED, NOTHING ELSE CAN BE DONE.
 *
 *    printf("      Set DomainState . . . . . . . . . . . . . . . . . . .     ");
 *
 *    //
 *    // Get the current value...
 *    //
 *
 *    NtStatus = SamQueryInformationDomain(
 *                   DomainHandle,
 *                   DomainStateInformation,
 *                   &Buffer1
 *                   );
 *    ASSERT( NT_SUCCESS(NtStatus) );
 *
 *    //
 *    // Change the field to a new value and write it out.
 *    //
 *
 *    if ( ((DOMAIN_STATE_INFORMATION *)Buffer1)->DomainServerState ==
 *         DomainServerEnabled ) {
 *        ((DOMAIN_STATE_INFORMATION *)Buffer1)->DomainServerState =
 *            DomainServerDisabled;
 *    } else {
 *        ((DOMAIN_STATE_INFORMATION *)Buffer1)->DomainServerState =
 *            DomainServerEnabled;
 *    }
 *
 *    NtStatus = SamSetInformationDomain(
 *                   DomainHandle,
 *                   DomainStateInformation,
 *                   Buffer1
 *                   );
 *    if ( NT_SUCCESS(NtStatus) ) {
 *
 *        //
 *        // Now check that the change was really made...
 *        //
 *
 *        NtStatus = SamQueryInformationDomain(
 *                       DomainHandle,
 *                       DomainStateInformation,
 *                       &Buffer2
 *                       );
 *        ASSERT(NT_SUCCESS( NtStatus ) );
 *        if (((DOMAIN_STATE_INFORMATION *)Buffer1)->DomainServerState ==
 *            ((DOMAIN_STATE_INFORMATION *)Buffer2)->DomainServerState    ) {
 *
 *                printf("Succeeded\n");
 *
 *        } else {
 *
 *            printf("Failed\n");
 *            printf("        Value queried doesn't match value written\n");
 *            printf("        Value Written is   0x%lx\n",
 *                (ULONG)((DOMAIN_STATE_INFORMATION *)Buffer1)->DomainServerState);
 *            printf("        Value Retrieved is 0x%lx\n",
 *                (ULONG)((DOMAIN_STATE_INFORMATION *)Buffer2)->DomainServerState);
 *
 *            TestStatus = FALSE;
 *
 *        }
 *
 *        SamFreeMemory( Buffer1 );
 *        SamFreeMemory( Buffer2 );
 *
 *    } else {
 *        printf("Failed\n");
 *        printf("        Completion status is 0x%lx\n", NtStatus);
 *        TestStatus = FALSE;
 *        SamFreeMemory( Buffer1 );
 *
 *    }
 */



/*
 *  CANT TEST SERVER ROLE SETTING WITHOUT BREAKING THE REST OF THE TEST.
 *  THE REASON IS, ONCE THE ROLE IS SET TO BACKUP, NOTHING ELSE CAN BE
 *  SET.
 *
 *   printf("      Set ServerRole  . . . . . . . . . . . . . . . . . . .     ");
 *
 *   //
 *   // Get the current value...
 *   //
 *
 *   NtStatus = SamQueryInformationDomain(
 *                  DomainHandle,
 *                  DomainServerRoleInformation,
 *                  &Buffer1
 *                  );
 *   ASSERT( NT_SUCCESS(NtStatus) );
 *
 *   //
 *   // Change the field to a new value and write it out.
 *   //
 *
 *   if ( ((DOMAIN_SERVER_ROLE_INFORMATION *)Buffer1)->DomainServerRole ==
 *        DomainServerRolePrimary ) {
 *       ((DOMAIN_SERVER_ROLE_INFORMATION *)Buffer1)->DomainServerRole =
 *           DomainServerRoleBackup;
 *   } else {
 *       ((DOMAIN_SERVER_ROLE_INFORMATION *)Buffer1)->DomainServerRole =
 *           DomainServerRolePrimary;
 *   }
 *
 *   NtStatus = SamSetInformationDomain(
 *                  DomainHandle,
 *                  DomainServerRoleInformation,
 *                  Buffer1
 *                  );
 *   if ( NT_SUCCESS(NtStatus) ) {
 *
 *       //
 *       // Now check that the change was really made...
 *       //
 *
 *       NtStatus = SamQueryInformationDomain(
 *                      DomainHandle,
 *                      DomainServerRoleInformation,
 *                      &Buffer2
 *                      );
 *       ASSERT(NT_SUCCESS( NtStatus ) );
 *       if (((DOMAIN_SERVER_ROLE_INFORMATION *)Buffer1)->DomainServerRole ==
 *           ((DOMAIN_SERVER_ROLE_INFORMATION *)Buffer2)->DomainServerRole    ) {
 *
 *               printf("Succeeded\n");
 *
 *       } else {
 *
 *           printf("Failed\n");
 *           printf("        Value queried doesn't match value written\n");
 *           printf("        Value Written is   0x%lx\n",
 *               (ULONG)((DOMAIN_SERVER_ROLE_INFORMATION *)Buffer1)->DomainServerRole);
 *           printf("        Value Retrieved is 0x%lx\n",
 *               (ULONG)((DOMAIN_SERVER_ROLE_INFORMATION *)Buffer2)->DomainServerRole);
 *
 *           TestStatus = FALSE;
 *
 *       }
 *
 *       SamFreeMemory( Buffer1 );
 *       SamFreeMemory( Buffer2 );
 *
 *   } else {
 *       printf("Failed\n");
 *       printf("        Completion status is 0x%lx\n", NtStatus);
 *       TestStatus = FALSE;
 *       SamFreeMemory( Buffer1 );
 *
 *   }
 */



    printf("      Set Password Information  . . . . . . . . . . . . . .     ");


    //
    // Get the current value...
    //

    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainPasswordInformation,
                   &Buffer1
                   );
    ASSERT( NT_SUCCESS(NtStatus) );

    //
    // Change a field to a new value and write it out.
    //

    if ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer1)->MinPasswordLength == 0 ) {
         ((DOMAIN_PASSWORD_INFORMATION *)Buffer1)->MinPasswordLength =  6;
    } else {
        ((DOMAIN_PASSWORD_INFORMATION *)Buffer1)->MinPasswordLength =   0;
    }

    //
    // Set PasswordProperties to COMPLEX so that tests run after this one
    // are a little more interesting.
    //

    ((DOMAIN_PASSWORD_INFORMATION *)Buffer1)->PasswordProperties |= DOMAIN_PASSWORD_COMPLEX;

    NtStatus = SamSetInformationDomain(
                   DomainHandle,
                   DomainPasswordInformation,
                   Buffer1
                   );
    if ( NT_SUCCESS(NtStatus) ) {

        //
        // Now check that the change was really made...
        //

        NtStatus = SamQueryInformationDomain(
                       DomainHandle,
                       DomainPasswordInformation,
                       &Buffer2
                       );
        ASSERT(NT_SUCCESS( NtStatus ) );
        if (((DOMAIN_PASSWORD_INFORMATION *)Buffer1)->MinPasswordLength ==
            ((DOMAIN_PASSWORD_INFORMATION *)Buffer2)->MinPasswordLength    ) {

                printf("Succeeded\n");

        } else {

            printf("Failed\n");
            printf("        Value queried doesn't match value written\n");
            printf("        Value Written is   0x%lx\n",
                (ULONG)((DOMAIN_PASSWORD_INFORMATION *)Buffer1)->MinPasswordLength);
            printf("        Value Retrieved is 0x%lx\n",
                (ULONG)((DOMAIN_PASSWORD_INFORMATION *)Buffer2)->MinPasswordLength);

            TestStatus = FALSE;

        }

        SamFreeMemory( Buffer1 );
        SamFreeMemory( Buffer2 );

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
        SamFreeMemory( Buffer1 );

    }



    printf("      Set Logoff Information  . . . . . . . . . . . . . . .     ");

    //
    // Get the current value...
    //

    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainLogoffInformation,
                   &Buffer1
                   );
    ASSERT( NT_SUCCESS(NtStatus) );

    //
    // Change the field to a new value and write it out.
    //

    if ( ((DOMAIN_LOGOFF_INFORMATION *)Buffer1)->ForceLogoff.LowPart == 0 ) {
         ((DOMAIN_LOGOFF_INFORMATION *)Buffer1)->ForceLogoff.LowPart = 1000;
    } else {
        ((DOMAIN_LOGOFF_INFORMATION *)Buffer1)->ForceLogoff.LowPart =   0;
    }

    NtStatus = SamSetInformationDomain(
                   DomainHandle,
                   DomainLogoffInformation,
                   Buffer1
                   );
    if ( NT_SUCCESS(NtStatus) ) {

        //
        // Now check that the change was really made...
        //

        NtStatus = SamQueryInformationDomain(
                       DomainHandle,
                       DomainLogoffInformation,
                       &Buffer2
                       );
        ASSERT(NT_SUCCESS( NtStatus ) );
        if (((DOMAIN_LOGOFF_INFORMATION *)Buffer1)->ForceLogoff.LowPart ==
            ((DOMAIN_LOGOFF_INFORMATION *)Buffer2)->ForceLogoff.LowPart    ) {

                printf("Succeeded\n");

        } else {

            printf("Failed\n");
            printf("        Value queried doesn't match value written\n");
            printf("        Value Written is   0x%lx\n",
                (ULONG)((DOMAIN_LOGOFF_INFORMATION *)Buffer1)->ForceLogoff.LowPart);
            printf("        Value Retrieved is 0x%lx\n",
                (ULONG)((DOMAIN_LOGOFF_INFORMATION *)Buffer2)->ForceLogoff.LowPart);

            TestStatus = FALSE;

        }

        SamFreeMemory( Buffer1 );
        SamFreeMemory( Buffer2 );

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
        SamFreeMemory( Buffer1 );

    }



    printf("      Set Modified  . . . . . . . . . . . . . . . . . . . .     ");


    NtStatus = SamSetInformationDomain(
                   DomainHandle,
                   DomainModifiedInformation,
                   &LargeInteger1
                   );

    if (NtStatus != STATUS_INVALID_INFO_CLASS) {

        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    } else {
        printf("Succeeded\n");
    }


    printf("      Set Lockout Information . . . . . . . . . . . . . . .     ");

    //
    // Get the current value...
    //

    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainLockoutInformation,
                   &Buffer1
                   );
    ASSERT( NT_SUCCESS(NtStatus) );

    //
    // Change the field to a new value and write it out.
    //

    if ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutDuration.LowPart == 0 ) {
         ((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutDuration.LowPart = 9000000;
    } else {
        ((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutDuration.LowPart =   0;
    }
    if ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutObservationWindow.LowPart == 0 ) {
         ((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutObservationWindow.LowPart = 8000000;
    } else {
        ((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutObservationWindow.LowPart =   0;
    }
    if ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutThreshold == 0 ) {
         ((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutThreshold =  2;
    } else {
        ((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutThreshold  =  0;
    }

    NtStatus = SamSetInformationDomain(
                   DomainHandle,
                   DomainLockoutInformation,
                   Buffer1
                   );
    if ( NT_SUCCESS(NtStatus) ) {

        //
        // Now check that the change was really made...
        //

        NtStatus = SamQueryInformationDomain(
                       DomainHandle,
                       DomainLockoutInformation,
                       &Buffer2
                       );
        ASSERT(NT_SUCCESS( NtStatus ) );
        if ( (((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutDuration.LowPart ==
             ((DOMAIN_LOCKOUT_INFORMATION *)Buffer2)->LockoutDuration.LowPart    ) &&
             (((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutObservationWindow.LowPart ==
             ((DOMAIN_LOCKOUT_INFORMATION *)Buffer2)->LockoutObservationWindow.LowPart    ) &&
             (((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutThreshold ==
             ((DOMAIN_LOCKOUT_INFORMATION *)Buffer2)->LockoutThreshold    ) ) {

                printf("Succeeded\n");

        } else {

            printf("Failed\n");
            printf("        Value queried doesn't match value written\n");
            printf("        Duration Written is   0x%lx\n",
                (ULONG)((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutDuration.LowPart);
            printf("        Duration  Retrieved is 0x%lx\n",
                (ULONG)((DOMAIN_LOCKOUT_INFORMATION *)Buffer2)->LockoutDuration.LowPart);
            printf("        Window Written is   0x%lx\n",
                (ULONG)((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutObservationWindow.LowPart);
            printf("        Window  Retrieved is 0x%lx\n",
                (ULONG)((DOMAIN_LOCKOUT_INFORMATION *)Buffer2)->LockoutObservationWindow.LowPart);
            printf("        Duration Written is   0x%lx\n",
                (ULONG)((DOMAIN_LOCKOUT_INFORMATION *)Buffer1)->LockoutThreshold);
            printf("        Duration  Retrieved is 0x%lx\n",
                (ULONG)((DOMAIN_LOCKOUT_INFORMATION *)Buffer2)->LockoutThreshold);

            TestStatus = FALSE;

        }

        SamFreeMemory( Buffer1 );
        SamFreeMemory( Buffer2 );

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
        SamFreeMemory( Buffer1 );

    }




    printf("      Set Domain Name . . . . . . . . . . . . . . . . . . .     ");


    NtStatus = SamSetInformationDomain(
                   DomainHandle,
                   DomainNameInformation,
                   &DummyName1
                   );

    if (NtStatus != STATUS_INVALID_INFO_CLASS) {

        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    } else {
        printf("Succeeded\n");
    }


    printf("      Set OEM Information . . . . . . . . . . . . . . . . .     ");

    //
    // Get the current value...
    //

    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainOemInformation,
                   &Buffer1
                   );
    ASSERT( NT_SUCCESS(NtStatus) );

    //
    // Change the field to a new value and write it out.
    //

    NameLength = ((DOMAIN_OEM_INFORMATION *)Buffer1)->OemInformation.Length;
    if (  NameLength == DummyName1.Length ) {
        ((DOMAIN_OEM_INFORMATION *)Buffer1)->OemInformation = DummyName2;
    } else {
        ((DOMAIN_OEM_INFORMATION *)Buffer1)->OemInformation = DummyName1;
    }

    NtStatus = SamSetInformationDomain(
                   DomainHandle,
                   DomainOemInformation,
                   Buffer1
                   );
    if ( NT_SUCCESS(NtStatus) ) {

        //
        // Now check that the change was really made...
        //

        NtStatus = SamQueryInformationDomain(
                       DomainHandle,
                       DomainOemInformation,
                       &Buffer2
                       );
        ASSERT(NT_SUCCESS( NtStatus ) );
        if (((DOMAIN_OEM_INFORMATION *)Buffer1)->OemInformation.Length ==
            ((DOMAIN_OEM_INFORMATION *)Buffer2)->OemInformation.Length    ) {

            printf("Succeeded\n");

        } else {

            printf("Failed\n");
            printf("        Value queried doesn't match value written\n");
            printf("        Value Written is   0x%lx\n",
                (ULONG)((DOMAIN_OEM_INFORMATION *)Buffer1)->OemInformation.Length);
            printf("        Value Retrieved is 0x%lx\n",
                (ULONG)((DOMAIN_OEM_INFORMATION *)Buffer2)->OemInformation.Length);

            TestStatus = FALSE;

        }

        SamFreeMemory( Buffer1 );
        SamFreeMemory( Buffer2 );

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
        SamFreeMemory( Buffer1 );

    }




    printf("      Set Replication Information . . . . . . . . . . . . .     ");

    //
    // Get the current value...
    //

    NtStatus = SamQueryInformationDomain(
                   DomainHandle,
                   DomainReplicationInformation,
                   &Buffer1
                   );
    ASSERT( NT_SUCCESS(NtStatus) );

    //
    // Change the field to a new value and write it out.
    //

    NameLength = ((DOMAIN_REPLICATION_INFORMATION *)Buffer1)->ReplicaSourceNodeName.Length;
    if (  NameLength == DummyName1.Length ) {
        ((DOMAIN_REPLICATION_INFORMATION *)Buffer1)->ReplicaSourceNodeName = DummyName2;
    } else {
        ((DOMAIN_REPLICATION_INFORMATION *)Buffer1)->ReplicaSourceNodeName = DummyName1;
    }

    NtStatus = SamSetInformationDomain(
                   DomainHandle,
                   DomainReplicationInformation,
                   Buffer1
                   );
    if ( NT_SUCCESS(NtStatus) ) {

        //
        // Now check that the change was really made...
        //

        NtStatus = SamQueryInformationDomain(
                       DomainHandle,
                       DomainReplicationInformation,
                       &Buffer2
                       );
        ASSERT(NT_SUCCESS( NtStatus ) );
        if (((DOMAIN_REPLICATION_INFORMATION *)Buffer1)->ReplicaSourceNodeName.Length ==
            ((DOMAIN_REPLICATION_INFORMATION *)Buffer2)->ReplicaSourceNodeName.Length    ) {

            printf("Succeeded\n");

        } else {

            printf("Failed\n");
            printf("        Value queried doesn't match value written\n");
            printf("        Value Written is   0x%lx\n",
                (ULONG)((DOMAIN_REPLICATION_INFORMATION *)Buffer1)->ReplicaSourceNodeName.Length);
            printf("        Value Retrieved is 0x%lx\n",
                (ULONG)((DOMAIN_REPLICATION_INFORMATION *)Buffer2)->ReplicaSourceNodeName.Length);

            TestStatus = FALSE;

        }

        SamFreeMemory( Buffer1 );
        SamFreeMemory( Buffer2 );

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
        SamFreeMemory( Buffer1 );

    }




    ///////////////////////////////////////////////////////////////////////////
    //                                                                       //
    // Create User/Group/Alias Suite                                         //
    //                                                                       //
    ///////////////////////////////////////////////////////////////////////////

    printf("    Create User/Group/Alias . . . . . . . . . . . . . . . .   Suite\n");


    printf("      Create Group  . . . . . . . . . . . . . . . . . . . .     ");

    RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );

    GroupRid = 0;
    GroupHandle = NULL;
    NtStatus = SamCreateGroupInDomain(
                   DomainHandle,
                   &AccountName,
                   GROUP_ALL_ACCESS,
                   &GroupHandle,
                   &GroupRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NT_SUCCESS(NtStatus)) {
        if ( (GroupHandle == NULL) || (GroupRid == 0) ) {

        printf("Failed\n");
        printf("        Invalid GroupHandle or GroupRid returned.\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        printf("        GroupHandle value is: 0x%lx\n", (ULONG)GroupHandle);
        printf("        GroupRid value is:    0x%lx\n", GroupRid);
        TestStatus = FALSE;
        } else {

            printf("Succeeded\n");
            SavedGroupRid = GroupRid;
            NtStatus = SamCloseHandle( GroupHandle );
            if (!NT_SUCCESS(NtStatus)) {
                printf("        SamCloseHandle() completion status is: 0x%lx\n", NtStatus);
            }
            ASSERT( NT_SUCCESS(NtStatus) );

        }

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }




    printf("      Create Duplicate Group  . . . . . . . . . . . . . . .     ");
    RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);

    //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );


    GroupRid = 0;
    GroupHandle = NULL;
    NtStatus = SamCreateGroupInDomain(
                   DomainHandle,
                   &AccountName,
                   GROUP_ALL_ACCESS,
                   &GroupHandle,
                   &GroupRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NtStatus != STATUS_GROUP_EXISTS) {

        printf("Failed\n");
        printf("        Completion status should be STATUS_GROUP_EXISTS\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        TestStatus = FALSE;

    } else {

        printf("Succeeded\n");

    }



    printf("      Create Alias  . . . . . . . . . . . . . . . . . . . .     ");

    RtlInitString( &AccountNameAnsi, ALIAS_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    AliasRid = 0;
    AliasHandle = NULL;
    NtStatus = SamCreateAliasInDomain(
                   DomainHandle,
                   &AccountName,
                   ALIAS_ALL_ACCESS,
                   &AliasHandle,
                   &AliasRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NT_SUCCESS(NtStatus)) {
        if ( (AliasHandle == NULL) || (AliasRid == 0) ) {

        printf("Failed\n");
        printf("        Invalid AliasHandle or AliasRid returned.\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        printf("        AliasHandle value is: 0x%lx\n", (ULONG)AliasHandle);
        printf("        AliasRid value is:    0x%lx\n", AliasRid);
        TestStatus = FALSE;
        } else {

            printf("Succeeded\n");
            SavedAliasRid = AliasRid;
            NtStatus = SamCloseHandle( AliasHandle );
            if (!NT_SUCCESS(NtStatus)) {
                printf("        SamCloseHandle() completion status is: 0x%lx\n", NtStatus);
            }
            ASSERT( NT_SUCCESS(NtStatus) );


            if (AliasRid == SavedGroupRid) {
                printf("      Create Group/Alias Comparison. . . . . . . . . . . . .     Failed\n");

                printf("        Same RID assigned to new alias and group.\n");
                TestStatus = FALSE;
            }
        }

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }




    printf("      Create another Alias  . . . . . . . . . . . . . . . .     ");

    RtlInitString( &AccountNameAnsi, ALIAS_NAME2 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    AliasRid = 0;
    AliasHandle = NULL;
    NtStatus = SamCreateAliasInDomain(
                   DomainHandle,
                   &AccountName,
                   ALIAS_ALL_ACCESS,
                   &AliasHandle,
                   &AliasRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NT_SUCCESS(NtStatus)) {
        if ( (AliasHandle == NULL) || (AliasRid == 0) ) {

        printf("Failed\n");
        printf("        Invalid AliasHandle or AliasRid returned.\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        printf("        AliasHandle value is: 0x%lx\n", (ULONG)AliasHandle);
        printf("        AliasRid value is:    0x%lx\n", AliasRid);
        TestStatus = FALSE;
        } else {

            printf("Succeeded\n");
            SavedAliasRid = AliasRid;
            NtStatus = SamCloseHandle( AliasHandle );
            if (!NT_SUCCESS(NtStatus)) {
                printf("        SamCloseHandle() completion status is: 0x%lx\n", NtStatus);
            }
            ASSERT( NT_SUCCESS(NtStatus) );


            if (AliasRid == SavedGroupRid) {
                printf("      Create Group/Alias Comparison. . . . . . . . . . . . .     Failed\n");

                printf("        Same RID assigned to new alias and group.\n");
                TestStatus = FALSE;
            }
        }

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }




    printf("      Create Duplicate Alias  . . . . . . . . . . . . . . .     ");
    RtlInitString( &AccountNameAnsi, ALIAS_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    AliasRid = 0;
    AliasHandle = NULL;
    NtStatus = SamCreateAliasInDomain(
                   DomainHandle,
                   &AccountName,
                   ALIAS_ALL_ACCESS,
                   &AliasHandle,
                   &AliasRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NtStatus != STATUS_ALIAS_EXISTS) {

        printf("Failed\n");
        printf("        Completion status should be STATUS_ALIAS_EXISTS\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        TestStatus = FALSE;

    } else {

        printf("Succeeded\n");

    }





    printf("      Create User . . . . . . . . . . . . . . . . . . . . .     ");

    RtlInitString( &AccountNameAnsi, USER_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    UserRid = 0;
    UserHandle = NULL;
    NtStatus = SamCreateUserInDomain(
                   DomainHandle,
                   &AccountName,
                   USER_ALL_ACCESS,
                   &UserHandle,
                   &UserRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NT_SUCCESS(NtStatus)) {
        if ( (UserHandle == NULL) || (UserRid == 0) ) {

        printf("Failed\n");
        printf("        Invalid UserHandle or UserRid returned.\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        printf("        UserHandle value is: 0x%lx\n", (ULONG)UserHandle);
        printf("        UserRid value is:    0x%lx\n", UserRid);
        TestStatus = FALSE;
        } else {

            printf("Succeeded\n");
            ValidUserHandle = UserHandle;


            if (UserRid == SavedGroupRid) {
                printf("      Create Group/User Comparison. . . . . . . . . . . . .     Failed\n");

                printf("        Same RID assigned to new user and group.\n");
                TestStatus = FALSE;
            }

            if (UserRid == SavedAliasRid) {
                printf("      Create Alias/User Comparison. . . . . . . . . . . . .     Failed\n");

                printf("        Same RID assigned to new user and alias.\n");
                TestStatus = FALSE;
            }
        }

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }







    printf("      Create Duplicate User . . . . . . . . . . . . . . . .     ");

    RtlInitString( &AccountNameAnsi, USER_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    UserRid = 0;
    UserHandle = NULL;
    NtStatus = SamCreateUserInDomain(
                   DomainHandle,
                   &AccountName,
                   USER_ALL_ACCESS,
                   &UserHandle,
                   &UserRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NtStatus != STATUS_USER_EXISTS) {

        printf("Failed\n");
        printf("        Completion status should be STATUS_USER_EXISTS\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        TestStatus = FALSE;

    } else {

        printf("Succeeded\n");

    }




    printf("      Create Group With Same Name As User . . . . . . . . .     ");

    RtlInitString( &AccountNameAnsi, USER_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    GroupRid = 0;
    GroupHandle = NULL;
    NtStatus = SamCreateGroupInDomain(
                   DomainHandle,
                   &AccountName,
                   GROUP_ALL_ACCESS,
                   &GroupHandle,
                   &GroupRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NtStatus != STATUS_USER_EXISTS) {

        printf("Failed\n");
        printf("        Completion status should be STATUS_USER_EXISTS\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        TestStatus = FALSE;

    } else {

        printf("Succeeded\n");

    }




    printf("      Create Group With Same Name As Alias. . . . . . . . .     ");

    RtlInitString( &AccountNameAnsi, ALIAS_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    GroupRid = 0;
    GroupHandle = NULL;
    NtStatus = SamCreateGroupInDomain(
                   DomainHandle,
                   &AccountName,
                   GROUP_ALL_ACCESS,
                   &GroupHandle,
                   &GroupRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NtStatus != STATUS_ALIAS_EXISTS) {

        printf("Failed\n");
        printf("        Completion status should be STATUS_ALIAS_EXISTS\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        TestStatus = FALSE;

    } else {

        printf("Succeeded\n");

    }



    printf("      Create Alias With Same Name As Group. . . . . . . . .     ");

    RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    AliasRid = 0;
    AliasHandle = NULL;
    NtStatus = SamCreateAliasInDomain(
                   DomainHandle,
                   &AccountName,
                   GROUP_ALL_ACCESS,
                   &AliasHandle,
                   &AliasRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NtStatus != STATUS_GROUP_EXISTS) {

        printf("Failed\n");
        printf("        Completion status should be STATUS_GROUP_EXISTS\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        TestStatus = FALSE;

    } else {

        printf("Succeeded\n");

    }



    printf("      Create User With Same Name As Group . . . . . . . . .     ");

    RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);

    //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );


    UserRid = 0;
    UserHandle = NULL;
    NtStatus = SamCreateUserInDomain(
                   DomainHandle,
                   &AccountName,
                   USER_ALL_ACCESS,
                   &UserHandle,
                   &UserRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NtStatus != STATUS_GROUP_EXISTS) {

        printf("Failed\n");
        printf("        Completion status should be STATUS_GROUP_EXISTS\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        TestStatus = FALSE;

    } else {

        printf("Succeeded\n");

    }



    printf("      Create User With Same Name As Alias . . . . . . . . .     ");

    RtlInitString( &AccountNameAnsi, ALIAS_NAME1 );
    NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
    TST_SUCCESS_ASSERT(NtStatus);


    UserRid = 0;
    UserHandle = NULL;
    NtStatus = SamCreateUserInDomain(
                   DomainHandle,
                   &AccountName,
                   USER_ALL_ACCESS,
                   &UserHandle,
                   &UserRid
                   );
    RtlFreeUnicodeString( &AccountName );

    if (NtStatus != STATUS_ALIAS_EXISTS) {

        printf("Failed\n");
        printf("        Completion status should be STATUS_ALIAS_EXISTS\n");
        printf("        Completion status is  0x%lx\n", NtStatus);
        TestStatus = FALSE;

    } else {

        printf("Succeeded\n");

    }



    ///////////////////////////////////////////////////////////////////////////
    //                                                                       //
    // Call server to test internal functions                                //
    //                                                                       //
    ///////////////////////////////////////////////////////////////////////////

    printf("\n");
    printf("    Test internal functions . . . . . . . . . . . . . . .   Suite\n");
    printf("      Test internal domain functions  . . . . . . . . . .       ");

    NtStatus = SamTestPrivateFunctionsDomain( DomainHandle );

    if ( NT_SUCCESS( NtStatus ) ) {

        printf("Succeeded.\n");

    } else {

        if ( NtStatus == STATUS_NOT_IMPLEMENTED ) {

            printf("Not Implemented\n");

        } else {

            printf("Failed.\n");
            printf("    Status = %lx\n", NtStatus );
            TestStatus = FALSE;
        }
    }

    printf("      Test internal user functions  . . . . . . . . . . .       ");

    if (ValidUserHandle == NULL) {

        printf("Test omitted - Valid User handle not available\n");
        TestStatus = FALSE;

    } else {

        NtStatus = SamTestPrivateFunctionsUser( ValidUserHandle );
        IgnoreStatus = SamCloseHandle( ValidUserHandle );
        ASSERT( NT_SUCCESS(IgnoreStatus) );

        if ( NT_SUCCESS( NtStatus ) ) {

            printf("Succeeded.\n");

        } else {

            if ( NtStatus == STATUS_NOT_IMPLEMENTED ) {

                printf("Not Implemented\n");

            } else {

                printf("Failed.\n");
                printf("    Status = %lx\n", NtStatus );
                TestStatus = FALSE;
            }
        }
    }


    ///////////////////////////////////////////////////////////////////////////
    //                                                                       //
    // Enumerate Users/Groups Suite                                          //
    //                                                                       //
    ///////////////////////////////////////////////////////////////////////////


    printf("    Enumerate Users/Groups/Aliases. . . . . . . . . . . .   Suite\n");

    printf("      Enumerate Groups - large prefered length  . . . . . .     ");


    EnumerationContext = 0;
    NtStatus = SamEnumerateGroupsInDomain(
                   DomainHandle,
                   &EnumerationContext,
                   &Buffer,
                   12000,                   // PreferedMaximumLength
                   &CountReturned
                   );
    AccountCount = CountReturned;       // Save for future test

    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
            if (NtStatus == STATUS_SUCCESS) {

                if (CountReturned > 1) {
                    printf("Succeeded\n");
                    for (i=0; i<CountReturned; i++) {
                        printf("            Rid/Name(%ld): 0x%lx / %wZ\n",i,
                               ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId,
                              &((PSAM_RID_ENUMERATION)(Buffer))[i].Name
                              );
                    }

                } else {
                    printf("Failed\n");
                    printf("        Completion status is 0x%lx\n", NtStatus);
                    printf("        Expected several entries to be returned.\n");
                    printf("        Received 0x%lx entries instead.\n", CountReturned);
                    TestStatus = FALSE;
                }

            } else {

                printf("Failed\n");
                printf("        Expected STATUS_MORE_ENTRIES to be returned.\n");
                printf("        Received 0x%lx instead.\n", NtStatus);
                printf("        Buffer        = 0x%lx\n", (ULONG)Buffer);
                printf("        CountReturned = 0x%lx\n", CountReturned);
                TestStatus = FALSE;
            }

            SamFreeMemory( Buffer );

        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;

    }




    printf("      Enumerate Groups - small prefered length  . . . . . .     ");


    for ( i=0; i<AccountCount; i++) {
        EnumerationContext = i;
        NtStatus = SamEnumerateGroupsInDomain(
                       DomainHandle,
                       &EnumerationContext,
                       &Buffer,
                       0,                   // PreferedMaximumLength
                       &CountReturned
                       );

        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {
                if ( ((i >= AccountCount -1) && (NtStatus == STATUS_SUCCESS)) ||
                     ((i <= AccountCount -1) && (NtStatus == STATUS_MORE_ENTRIES))  ) {

                    if (CountReturned != 1) {
                        printf("Failed\n");
                        printf("        Completion status is 0x%lx\n", NtStatus);
                        printf("        Expected one entry to be returned.\n");
                        printf("        Received 0x%lx entries instead.\n", CountReturned);
                        TestStatus = FALSE;
                        i = AccountCount + 100;
                    }

                } else {

                    printf("Failed\n");
                    if (i < AccountCount -1 ) {
                        printf("        Expected STATUS_MORE_ENTRIES to be returned.\n");
                    } else {
                        printf("        Expected STATUS_SUCCESS to be returned.\n");
                    }
                    printf("        Received 0x%lx instead.\n", NtStatus);
                    printf("        Buffer        = 0x%lx\n", (ULONG)Buffer);
                    printf("        CountReturned = 0x%lx\n", CountReturned);
                    TestStatus = FALSE;
                    i = AccountCount + 100;
                }

                SamFreeMemory( Buffer );

            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                i = AccountCount + 100;
            }

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
            i = AccountCount + 100;

        }
    }

    if ( i == AccountCount) {
        printf("Succeeded\n");
    }




    printf("      Enumerate Aliases - large prefered length . . . . . .     ");


    EnumerationContext = 0;
    NtStatus = SamEnumerateAliasesInDomain(
                   DomainHandle,
                   &EnumerationContext,
                   &Buffer,
                   12000,                   // PreferedMaximumLength
                   &CountReturned
                   );
    AccountCount = CountReturned;       // Save for future test

    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
            if (NtStatus == STATUS_SUCCESS) {

                if (CountReturned > 1) {
                    printf("Succeeded\n");
                    for (i=0; i<CountReturned; i++) {
                        printf("            Rid/Name(%ld): 0x%lx / %wZ\n",i,
                               ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId,
                              &((PSAM_RID_ENUMERATION)(Buffer))[i].Name
                              );
                    }

                } else {
                    printf("Failed\n");
                    printf("        Completion status is 0x%lx\n", NtStatus);
                    printf("        Expected several entries to be returned.\n");
                    printf("        Received 0x%lx entries instead.\n", CountReturned);
                    TestStatus = FALSE;
                }

            } else {

                printf("Failed\n");
                printf("        Expected STATUS_MORE_ENTRIES to be returned.\n");
                printf("        Received 0x%lx instead.\n", NtStatus);
                printf("        Buffer        = 0x%lx\n", (ULONG)Buffer);
                printf("        CountReturned = 0x%lx\n", CountReturned);
                TestStatus = FALSE;
            }

            SamFreeMemory( Buffer );

        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;

    }




    printf("      Enumerate Aliases - small prefered length . . . . . .     ");


    for ( i=0; i<AccountCount; i++) {
        EnumerationContext = i;
        NtStatus = SamEnumerateAliasesInDomain(
                       DomainHandle,
                       &EnumerationContext,
                       &Buffer,
                       0,                   // PreferedMaximumLength
                       &CountReturned
                       );

        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {
                if ( ((i >= AccountCount -1) && (NtStatus == STATUS_SUCCESS)) ||
                     ((i <= AccountCount -1) && (NtStatus == STATUS_MORE_ENTRIES))  ) {

                    if (CountReturned != 1) {
                        printf("Failed\n");
                        printf("        Completion status is 0x%lx\n", NtStatus);
                        printf("        Expected one entry to be returned.\n");
                        printf("        Received 0x%lx entries instead.\n", CountReturned);
                        TestStatus = FALSE;
                        i = AccountCount + 100;
                    }

                } else {

                    printf("Failed\n");
                    if (i < AccountCount -1 ) {
                        printf("        Expected STATUS_MORE_ENTRIES to be returned.\n");
                    } else {
                        printf("        Expected STATUS_SUCCESS to be returned.\n");
                    }
                    printf("        Received 0x%lx instead.\n", NtStatus);
                    printf("        Buffer        = 0x%lx\n", (ULONG)Buffer);
                    printf("        CountReturned = 0x%lx\n", CountReturned);
                    TestStatus = FALSE;
                    i = AccountCount + 100;
                }

                SamFreeMemory( Buffer );

            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                i = AccountCount + 100;
            }

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
            i = AccountCount + 100;

        }
    }

    if ( i == AccountCount) {
        printf("Succeeded\n");
    }





    printf("      Enumerate Users  - large prefered length  . . . . . .     ");


    EnumerationContext = 0;
    NtStatus = SamEnumerateUsersInDomain(
                   DomainHandle,
                   &EnumerationContext,
                   0,
                   &Buffer,
                   12000,                   // PreferedMaximumLength
                   &CountReturned
                   );
    AccountCount = CountReturned;       // Save for future test

    if (NT_SUCCESS(NtStatus)) {
        if (Buffer != NULL) {
            if (NtStatus == STATUS_SUCCESS) {

                if (CountReturned > 1) {
                    printf("Succeeded\n");
                    for (i=0; i<CountReturned; i++) {
                        printf("            Rid/Name(%ld): 0x%lx / %wZ\n",i,
                               ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId,
                              &((PSAM_RID_ENUMERATION)(Buffer))[i].Name
                              );
                    }

                } else {
                    printf("Failed\n");
                    printf("        Completion status is 0x%lx\n", NtStatus);
                    printf("        Expected several entries to be returned.\n");
                    printf("        Received 0x%lx entries instead.\n", CountReturned);
                    TestStatus = FALSE;
                }

            } else {

                printf("Failed\n");
                printf("        Expected STATUS_MORE_ENTRIES to be returned.\n");
                printf("        Received 0x%lx instead.\n", NtStatus);
                printf("        Buffer        = 0x%lx\n", (ULONG)Buffer);
                printf("        CountReturned = 0x%lx\n", CountReturned);
                TestStatus = FALSE;
            }

            SamFreeMemory( Buffer );

        } else {
            printf("Failed\n");
            printf("        Buffer address not set on return.\n");
            printf("        RPC should have allocated a buffer.\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;

    }




    printf("      Enumerate Users  - small prefered length  . . . . . .     ");


    for ( i=0; i<AccountCount; i++) {
        EnumerationContext = i;
        NtStatus = SamEnumerateUsersInDomain(
                       DomainHandle,
                       &EnumerationContext,
                       0,
                       &Buffer,
                       0,                   // PreferedMaximumLength
                       &CountReturned
                       );

        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {
                if ( ((i >= AccountCount -1) && (NtStatus == STATUS_SUCCESS)) ||
                     ((i <= AccountCount -1) && (NtStatus == STATUS_MORE_ENTRIES))  ) {

                    if (CountReturned != 1) {
                        printf("Failed\n");
                        printf("        Completion status is 0x%lx\n", NtStatus);
                        printf("        Expected one entry to be returned.\n");
                        printf("        Received 0x%lx entries instead.\n", CountReturned);
                        TestStatus = FALSE;
                        i = AccountCount + 100;
                    }

                } else {

                    printf("Failed\n");
                    if (i < AccountCount -1 ) {
                        printf("        Expected STATUS_MORE_ENTRIES to be returned.\n");
                    } else {
                        printf("        Expected STATUS_SUCCESS to be returned.\n");
                    }
                    printf("        Received 0x%lx instead.\n", NtStatus);
                    printf("        Buffer        = 0x%lx\n", (ULONG)Buffer);
                    printf("        CountReturned = 0x%lx\n", CountReturned);
                    TestStatus = FALSE;
                    i = AccountCount + 100;
                }

                SamFreeMemory( Buffer );

            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                i = AccountCount + 100;
            }

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
            i = AccountCount + 100;

        }
    }

    if ( i == AccountCount) {
        printf("Succeeded\n");
    }










    ///////////////////////////////////////////////////////////////////////////
    //                                                                       //
    // Lookup Names/IDs Suite                                                //
    //                                                                       //
    ///////////////////////////////////////////////////////////////////////////


    // LATER add alias search to lookup name suite.....


    printf("\n");
    printf("    Lookup Names/IDs  . . . . . . . . . . . . . . . . . .   Suite\n");


    printf("      Lookup Names (all existing) . . . . . . . . . . . . .     ");

    NtStatus = SamLookupNamesInDomain(
                   DomainHandle,
                   ALL_NAMES_COUNT,
                   &AllNames[0],
                   &LookedUpRids,
                   &LookedUpUses
                   );


    if (NT_SUCCESS(NtStatus)) {
        ASSERT( LookedUpRids != NULL );
        ASSERT( LookedUpUses != NULL );

        if (
            (LookedUpRids[0] == AllRids[0]) && (LookedUpUses[0] == AllUses[0])
                                            &&
            (LookedUpRids[1] == AllRids[1]) && (LookedUpUses[1] == AllUses[1])
                                            &&
            (LookedUpRids[2] == AllRids[2]) && (LookedUpUses[2] == AllUses[2])
            ) {


            printf("Succeeded\n");


        } else {
            printf("Failed\n");
            printf("        Rids or Uses dont match expected values.\n");
            printf("        Expected Rids:  0x%lx, 0x%lx, 0x%lx\n",
                AllRids[0], AllRids[1], AllRids[2]);
            printf("        Received Rids:  0x%lx, 0x%lx, 0x%lx\n",
                LookedUpRids[0], LookedUpRids[1], LookedUpRids[2]);
            printf("        Expected Uses:  0x%lx, 0x%lx, 0x%lx\n",
                AllUses[0], AllUses[1], AllUses[2]);
            printf("        Received Uses:  0x%lx, 0x%lx, 0x%lx\n",
                LookedUpUses[0], LookedUpUses[1], LookedUpUses[2]);
            TestStatus = FALSE;
        }


        SamFreeMemory( LookedUpRids );
        SamFreeMemory( LookedUpUses );

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }




    printf("      Lookup Names (Some existing)  . . . . . . . . . . . .     ");

    NtStatus = SamLookupNamesInDomain(
                   DomainHandle,
                   SOME_NAMES_COUNT,
                   &SomeNames[0],
                   &LookedUpRids,
                   &LookedUpUses
                   );


    if (NtStatus == STATUS_SOME_NOT_MAPPED) {
        ASSERT( LookedUpRids != NULL );
        ASSERT( LookedUpUses != NULL );

        if (
            (LookedUpRids[0] == SomeRids[0]) && (LookedUpUses[0] == SomeUses[0])
                                             &&
            (LookedUpRids[1] == SomeRids[1]) && (LookedUpUses[1] == SomeUses[1])
                                             &&
            (LookedUpRids[2] == SomeRids[2]) && (LookedUpUses[2] == SomeUses[2])
                                             &&
            (LookedUpRids[3] == SomeRids[3]) && (LookedUpUses[3] == SomeUses[3])
                                             &&
            (LookedUpRids[4] == SomeRids[4]) && (LookedUpUses[4] == SomeUses[4])
                                             &&
            (LookedUpRids[5] == SomeRids[5]) && (LookedUpUses[5] == SomeUses[5])
                                             &&
            (LookedUpRids[6] == SomeRids[6]) && (LookedUpUses[6] == SomeUses[6])
            ) {


            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Rids or Uses dont match expected values.\n");
            printf("        Expected Rids:  0x%lx, 0x%lx, 0x%lx, 0x%lx,  0x%lx, 0x%lx, 0x%lx\n",
                SomeRids[0], SomeRids[1], SomeRids[2], SomeRids[3], SomeRids[4], SomeRids[5], SomeRids[6]);
            printf("        Received Rids:  0x%lx, 0x%lx, 0x%lx, 0x%lx,  0x%lx, 0x%lx, 0x%lx\n",
                LookedUpRids[0], LookedUpRids[1], LookedUpRids[2], LookedUpRids[3], LookedUpRids[4], LookedUpRids[5], LookedUpRids[6]);
            printf("        Expected Uses:  0x%lx, 0x%lx, 0x%lx, 0x%lx,  0x%lx, 0x%lx, 0x%lx\n",
                SomeUses[0], SomeUses[1], SomeUses[2], SomeUses[3], SomeUses[4], SomeUses[5], SomeUses[6]);
            printf("        Received Uses:  0x%lx, 0x%lx, 0x%lx, 0x%lx,  0x%lx, 0x%lx, 0x%lx\n",
                LookedUpUses[0], LookedUpUses[1], LookedUpUses[2], LookedUpUses[3], LookedUpUses[4], LookedUpUses[5], LookedUpUses[2]);
            TestStatus = FALSE;
        }


        SamFreeMemory( LookedUpRids );
        SamFreeMemory( LookedUpUses );

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }



    printf("      Lookup Names (None existing)  . . . . . . . . . . . .     ");

    NtStatus = SamLookupNamesInDomain(
                   DomainHandle,
                   NO_NAMES_COUNT,
                   &NoNames[0],
                   &LookedUpRids,
                   &LookedUpUses
                   );


    if (NtStatus == STATUS_NONE_MAPPED) {
        ASSERT( LookedUpRids == NULL );
        ASSERT( LookedUpUses == NULL );

        printf("Succeeded\n");

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }


 
    printf("      Lookup SIDs (all existing)  . . . . . . . . . . . . .     ");

    NtStatus = SamLookupIdsInDomain(
                   DomainHandle,
                   ALL_NAMES_COUNT,
                   &AllRids[0],
                   &LookedUpNames,
                   &LookedUpUses
                   );


    if (NT_SUCCESS(NtStatus)) {
        ASSERT( LookedUpUses  != NULL );
        ASSERT( LookedUpNames != NULL );
        ASSERT( LookedUpNames[0].Buffer != NULL );
        ASSERT( LookedUpNames[1].Buffer != NULL );
        ASSERT( LookedUpNames[2].Buffer != NULL );

        if (
            (LookedUpUses[0] == AllUses[0]) &&
            (LookedUpUses[1] == AllUses[1]) &&
            (LookedUpUses[2] == AllUses[2]) &&
            !RtlCompareString( (PSTRING)&LookedUpNames[0], (PSTRING)&AllNames[0], TRUE ) &&
            !RtlCompareString( (PSTRING)&LookedUpNames[1], (PSTRING)&AllNames[1], TRUE ) &&
            !RtlCompareString( (PSTRING)&LookedUpNames[2], (PSTRING)&AllNames[2], TRUE )
            ) {


            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Names or Uses dont match expected values.\n");
            printf("        Expected Name[0]:  %wZ\n", &AllNames[0] );
            printf("        Received Name[0]:  %wZ\n", &LookedUpNames[0] );
            printf("        Expected Name[1]:  %wZ\n", &AllNames[1] );
            printf("        Received Name[1]:  %wZ\n", &LookedUpNames[1] );
            printf("        Expected Name[2]:  %wZ\n", &AllNames[2] );
            printf("        Received Name[2]:  %wZ\n", &LookedUpNames[2] );

            printf("        Expected Uses:  0x%lx, 0x%lx, 0x%lx\n",
                AllUses[0], AllUses[1], AllUses[2]);
            printf("        Received Uses:  0x%lx, 0x%lx, 0x%lx\n",
                LookedUpUses[0], LookedUpUses[1], LookedUpUses[2]);
            TestStatus = FALSE;
        }


        SamFreeMemory( LookedUpUses );
        SamFreeMemory( LookedUpNames );

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }




    printf("      Lookup SIDs (Some existing) . . . . . . . . . . . . .     ");

    NtStatus = SamLookupIdsInDomain(
                   DomainHandle,
                   SOME_NAMES_COUNT,
                   &SomeRids[0],
                   &LookedUpNames,
                   &LookedUpUses
                   );


    if (NtStatus == STATUS_SOME_NOT_MAPPED) {
        ASSERT( LookedUpUses  != NULL );
        ASSERT( LookedUpNames != NULL );
        ASSERT( LookedUpNames[0].Buffer != NULL );
        ASSERT( LookedUpNames[1].Buffer != NULL );
        ASSERT( LookedUpNames[2].Buffer == NULL );  // Unknown
        ASSERT( LookedUpNames[3].Buffer == NULL );  // Unknown
        ASSERT( LookedUpNames[4].Buffer == NULL );  // Unknown
        ASSERT( LookedUpNames[5].Buffer != NULL );
        ASSERT( LookedUpNames[6].Buffer == NULL );  // Unknown

        if (
            (LookedUpUses[0] == SomeUses[0]) &&
            (LookedUpUses[1] == SomeUses[1]) &&
            (LookedUpUses[2] == SomeUses[2]) &&
            !RtlCompareString( (PSTRING)&LookedUpNames[0], (PSTRING)&SomeNames[0], TRUE ) &&
            !RtlCompareString( (PSTRING)&LookedUpNames[1], (PSTRING)&SomeNames[1], TRUE ) &&
            !RtlCompareString( (PSTRING)&LookedUpNames[5], (PSTRING)&SomeNames[5], TRUE )
            ) {


            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Names or Uses dont match expected values.\n");
            printf("        Expected Name[0]:  %wZ\n", &SomeNames[0] );
            printf("        Received Name[0]:  %wZ\n", &LookedUpNames[0] );
            printf("        Expected Name[1]:  %wZ\n", &SomeNames[1] );
            printf("        Received Name[1]:  %wZ\n", &LookedUpNames[1] );
            printf("                 Name[2]:  (Unknown)\n");
            printf("                 Name[3]:  (Unknown)\n");
            printf("                 Name[4]:  (Unknown)\n");
            printf("        Expected Name[5]:  %wZ\n", &SomeNames[5] );
            printf("        Received Name[5]:  %wZ\n", &LookedUpNames[5] );
            printf("                 Name[6]:  (Unknown)\n");

            printf("        Expected Uses:  0x%lx, 0x%lx, 0x%lx, 0x%lx,  0x%lx, 0x%lx, 0x%lx\n",
                SomeUses[0], SomeUses[1], SomeUses[2], SomeUses[3], SomeUses[4], SomeUses[5], SomeUses[6]);
            printf("        Received Uses:  0x%lx, 0x%lx, 0x%lx, 0x%lx,  0x%lx, 0x%lx, 0x%lx\n",
                LookedUpUses[0], LookedUpUses[1], LookedUpUses[2], LookedUpUses[3], LookedUpUses[4], LookedUpUses[5], LookedUpUses[2]);
            TestStatus = FALSE;
        }


        SamFreeMemory( LookedUpUses );
        SamFreeMemory( LookedUpNames );

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }




    printf("      Lookup SIDs (None existing) . . . . . . . . . . . . .     ");

    NtStatus = SamLookupIdsInDomain(
                   DomainHandle,
                   NO_NAMES_COUNT,
                   &NoRids[0],
                   &LookedUpNames,
                   &LookedUpUses
                   );


    if (NtStatus == STATUS_NONE_MAPPED) {
        ASSERT( LookedUpUses  == NULL );
        ASSERT( LookedUpNames == NULL );

        printf("Succeeded\n");

    } else {
        printf("Failed\n");
        printf("        Completion status is 0x%lx\n", NtStatus);
        TestStatus = FALSE;
    }







    return TestStatus;
}


///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Group  Object Test Suite                                                  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////


BOOLEAN
GroupTestSuite(
    HANDLE DomainHandle,
    ULONG  Pass
    )

{
    NTSTATUS            NtStatus, IgnoreStatus;
    HANDLE              GroupHandle1, GroupHandle2, UserHandle1;
    ULONG               CountReturned, NameLength, i, MemberCount;
    ULONG               UserRid, GroupRid;
    PVOID               Buffer, Buffer1, Buffer2;
    SAM_ENUMERATE_HANDLE EnumerationContext;
    PULONG              Members, Attributes;
    PSID_NAME_USE       LookedUpUses;
    PULONG              LookedUpRids;
    UNICODE_STRING      AccountNames[10], AccountName;
    STRING              AccountNameAnsi;

    BOOLEAN             IndividualTestSucceeded, DeleteUser;
    BOOLEAN             TestStatus = TRUE;


    if (Pass == 1) {
        //
        // This test suite assumes that lookup and enumeration API funciton
        // properly.
        //

        printf("\n");
        printf("\n");
        printf("  Group (Pass #1) . . . . . . . . . . . . . . . . . . .   Test\n");

        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Open Group Suite                                                      //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("    Open Group  . . . . . . . . . . . . . . . . . . . . .   Suite\n");
        printf("      Open Groups . . . . . . . . . . . . . . . . . . . . .     ");
        IndividualTestSucceeded = TRUE;
        EnumerationContext = 0;
        NtStatus = SamEnumerateGroupsInDomain(
                       DomainHandle,
                       &EnumerationContext,
                       &Buffer,
                       12000,                   // PreferedMaximumLength
                       &CountReturned
                       );

        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(Buffer != NULL);
        ASSERT(CountReturned > 0);

        for (i=0; i<CountReturned; i++) {

            NtStatus = SamOpenGroup(
                           DomainHandle,
                           GROUP_ALL_ACCESS,
                           ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId,
                           &GroupHandle1
                           );

            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamOpenGroup(
                               DomainHandle,
                               GENERIC_READ,
                               ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId,
                               &GroupHandle2
                               );

                if (NT_SUCCESS(NtStatus)) {
                    IgnoreStatus = SamCloseHandle( GroupHandle2 );
                    ASSERT( NT_SUCCESS(IgnoreStatus) );
                } else {
                    printf("Failed\n");
                    printf("        Completion status is 0x%lx\n", NtStatus);
                    printf("        Failed opening group second time.\n");
                    printf("        Rid of account is:   0x%lx\n",
                        ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId);
                    printf("        Name of account is:  %wZ\n",
                        &((PSAM_RID_ENUMERATION)(Buffer))[i].Name );
                    TestStatus = FALSE;
                    IndividualTestSucceeded = FALSE;
                }

                IgnoreStatus = SamCloseHandle( GroupHandle1 );
                ASSERT( NT_SUCCESS(IgnoreStatus) );

            } else {

                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                printf("        Failed opening group for first time.\n");
                printf("        Rid of account is:   0x%lx\n",
                    ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId);
                printf("        Name of account is:  %wZ\n",
                    &((PSAM_RID_ENUMERATION)(Buffer))[i].Name );
                TestStatus = FALSE;
                IndividualTestSucceeded = FALSE;
            }

            if (!IndividualTestSucceeded) {
                printf("                                                                ");
            }
        }


        SamFreeMemory( Buffer );
        if (IndividualTestSucceeded) {
            printf("Succeeded\n");
        }



        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Query     Group Suite                                                 //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Query Group . . . . . . . . . . . . . . . . . . . . .   Suite\n");

        printf("      Query Group General Information . . . . . . . . . . .     ");


        NtStatus = SamOpenGroup(
                       DomainHandle,
                       GROUP_READ_INFORMATION,
                       DOMAIN_GROUP_RID_USERS,
                       &GroupHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationGroup(
                       GroupHandle1,
                       GroupGeneralInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((GROUP_GENERAL_INFORMATION *)Buffer)->Name.MaximumLength > 0) &&
                     (((GROUP_GENERAL_INFORMATION *)Buffer)->Name.Buffer != NULL)  ) {

                    printf("Succeeded\n");

                    printf("        Member Count is:  0x%lx\n",
                     (((GROUP_GENERAL_INFORMATION *)Buffer)->MemberCount) );
                    printf("        Attributes are:   0x%lx\n",
                     (((GROUP_GENERAL_INFORMATION *)Buffer)->Attributes) );
                    printf("        Group Name is:    %wZ\n",
                     &(((GROUP_GENERAL_INFORMATION *)Buffer)->Name) );



                } else {
                    printf("Failed\n");
                    printf("        Group Name not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( GroupHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query Group Name Information  . . . . . . . . . . . .     ");


        NtStatus = SamOpenGroup(
                       DomainHandle,
                       GROUP_READ_INFORMATION,
                       DOMAIN_GROUP_RID_USERS,
                       &GroupHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationGroup(
                       GroupHandle1,
                       GroupNameInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((GROUP_NAME_INFORMATION *)Buffer)->Name.MaximumLength > 0) &&
                     (((GROUP_NAME_INFORMATION *)Buffer)->Name.Buffer != NULL)  ) {

                    printf("Succeeded\n");

                    printf("        Group Name is:    %wZ\n",
                     &(((GROUP_NAME_INFORMATION *)Buffer)->Name) );



                } else {
                    printf("Failed\n");
                    printf("        Group Name not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( GroupHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query Group Admin Comment Information . . . . . . . .     ");


        NtStatus = SamOpenGroup(
                       DomainHandle,
                       GROUP_READ_INFORMATION,
                       DOMAIN_GROUP_RID_USERS,
                       &GroupHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationGroup(
                       GroupHandle1,
                       GroupAdminCommentInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((GROUP_ADM_COMMENT_INFORMATION *)Buffer)->AdminComment.MaximumLength >= 0) ) {

                    printf("Succeeded\n");

                    printf("        Group Admin Comment is:    %wZ\n",
                     &(((GROUP_ADM_COMMENT_INFORMATION *)Buffer)->AdminComment) );



                } else {
                    printf("Failed\n");
                    printf("        Group Admin Comment not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( GroupHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query Group Attribute Information . . . . . . . . . .     ");


        NtStatus = SamOpenGroup(
                       DomainHandle,
                       GROUP_READ_INFORMATION,
                       DOMAIN_GROUP_RID_USERS,
                       &GroupHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationGroup(
                       GroupHandle1,
                       GroupAttributeInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {


                printf("Succeeded\n");

                printf("        Attributes are:   0x%lx\n",
                 (((GROUP_ATTRIBUTE_INFORMATION *)Buffer)->Attributes) );


                SamFreeMemory( Buffer );

            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( GroupHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Get Members Of Group Suite                                            //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Get Members . . . . . . . . . . . . . . . . . . . . .   Suite\n");

        printf("      Get Members of Well-Known Account . . . . . . . . . .     ");

        NtStatus = SamOpenGroup(
                       DomainHandle,
                       GROUP_LIST_MEMBERS,
                       DOMAIN_GROUP_RID_USERS,
                       &GroupHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamGetMembersInGroup(
                       GroupHandle1,
                       &Members,
                       &Attributes,
                       &MemberCount
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Members != NULL || Attributes != NULL) {

                printf("Succeeded\n");


                printf("       Member Count:    %d Users\n", MemberCount);
                for ( i=0; i<MemberCount; i++) {

                    printf("       User[%d] Rid/Attributes:      0x%lx/0x%lx\n",
                        i, Members[i], Attributes[i]);


                }

                SamFreeMemory( Members );
                SamFreeMemory( Attributes );


            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( GroupHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );



        printf("      Get Members of Empty Group. . . . . . . . . . . . . .     ");

        //
        // This group was created earlier in the test
        //

        RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamLookupNamesInDomain(
                       DomainHandle,
                       1,
                       &AccountNames[0],
                       &LookedUpRids,
                       &LookedUpUses
                       );
        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(LookedUpUses[0] == SidTypeGroup);
        RtlFreeUnicodeString( &AccountNames[0] );



        GroupHandle1 = NULL;

        NtStatus = SamOpenGroup( DomainHandle, GROUP_LIST_MEMBERS, LookedUpRids[0], &GroupHandle1 );
        TST_SUCCESS_ASSERT(NtStatus);
        SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );

        NtStatus = SamGetMembersInGroup(
                       GroupHandle1,
                       &Members,
                       &Attributes,
                       &MemberCount
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (MemberCount == 0) {

                printf("Succeeded\n");




            } else {
                printf("Failed\n");
                printf("        Buffer addresses  set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                printf("       Member Count:    %d\n", MemberCount);
                for ( i=0; i<MemberCount; i++) {

                    printf("       User[%d] Rid/Attributes:      0x%lx/0x%lx\n",
                        i, Members[i], Attributes[i]);
                }

                SamFreeMemory( Members );
                SamFreeMemory( Attributes );
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( GroupHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );


        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Set Group Suite  (pass 1)                                             //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Set Group . . . . . . . . . . . . . . . . . . . . . .   Suite\n");


        printf("      Set Attribute . . . . . . . . . . . . . . . . . . . .     ");
        NtStatus = SamOpenGroup(
                       DomainHandle,
                       GROUP_WRITE_ACCOUNT | GROUP_READ_INFORMATION,
                       DOMAIN_GROUP_RID_USERS,
                       &GroupHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer1 = NULL;
        NtStatus = SamQueryInformationGroup(
                       GroupHandle1,
                       GroupAttributeInformation,
                       &Buffer1
                       );
        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(Buffer1 != NULL);

        //
        // Change the value and write it back
        //

        ((GROUP_ATTRIBUTE_INFORMATION *)Buffer1)->Attributes ^=
            SE_GROUP_ENABLED_BY_DEFAULT;


        NtStatus = SamSetInformationGroup(
                       GroupHandle1,
                       GroupAttributeInformation,
                       Buffer1
                       );
        if (NT_SUCCESS(NtStatus)) {

            //
            // Check the written value to make sure it stuck
            //

            Buffer2 = NULL;
            NtStatus = SamQueryInformationGroup(
                           GroupHandle1,
                           GroupAttributeInformation,
                           &Buffer2
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer2 != NULL);

            if (((GROUP_ATTRIBUTE_INFORMATION *)Buffer1)->Attributes ==
                ((GROUP_ATTRIBUTE_INFORMATION *)Buffer2)->Attributes   ) {

                printf("Succeeded\n");

                SamFreeMemory( Buffer2 );

            } else {
                printf("Failed\n");
                printf("        Returned Value Doesn't Match Set Value.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        SamFreeMemory( Buffer1 );
        IgnoreStatus = SamCloseHandle( GroupHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );





        printf("      Set Admin Comment . . . . . . . . . . . . . . . . . .     ");

            NtStatus = SamOpenGroup(
                           DomainHandle,
                           GROUP_WRITE_ACCOUNT | GROUP_READ_INFORMATION,
                           DOMAIN_GROUP_RID_USERS,
                           &GroupHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // Get the current value...
            //

            Buffer1 = NULL;
            NtStatus = SamQueryInformationGroup(
                           GroupHandle1,
                           GroupAdminCommentInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);


            //
            // Change the field to a new value and write it out.
            //

            NameLength = ((GROUP_ADM_COMMENT_INFORMATION *)Buffer1)->AdminComment.Length;
            if (  NameLength == DummyString1.Length ) {
                ((GROUP_ADM_COMMENT_INFORMATION *)Buffer1)->AdminComment = DummyString2;
            } else {
                ((GROUP_ADM_COMMENT_INFORMATION *)Buffer1)->AdminComment = DummyString1;
            }

            NtStatus = SamSetInformationGroup(
                           GroupHandle1,
                           GroupAdminCommentInformation,
                           Buffer1
                           );
            if ( NT_SUCCESS(NtStatus) ) {

                //
                // Now check that the change was really made...
                //

                Buffer2 = NULL;
                NtStatus = SamQueryInformationGroup(
                               GroupHandle1,
                               GroupAdminCommentInformation,
                               &Buffer2
                               );
                ASSERT(NT_SUCCESS( NtStatus ) );
                if (
                    !RtlCompareString(
                        (PSTRING)&((GROUP_ADM_COMMENT_INFORMATION *)Buffer1)->AdminComment,
                        (PSTRING)&((GROUP_ADM_COMMENT_INFORMATION *)Buffer2)->AdminComment,
                        TRUE)
                    ) {

                    printf("Succeeded\n");

                } else {

                    printf("Failed\n");
                    printf("        Value queried doesn't match value written\n");
                    printf("        Value Written is   %wZ\n",
                        (PUNICODE_STRING)&((GROUP_ADM_COMMENT_INFORMATION *)Buffer1)->AdminComment);
                    printf("        Value Retrieved is %wZ\n",
                        (PUNICODE_STRING)&((GROUP_ADM_COMMENT_INFORMATION *)Buffer2)->AdminComment);

                    TestStatus = FALSE;

                }

                SamFreeMemory( Buffer1 );
                SamFreeMemory( Buffer2 );

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                SamFreeMemory( Buffer1 );

            }






    } // END PASS #1
    if (Pass == 2) {

        printf("\n");
        printf("\n");
        printf("  Group (Pass #2) . . . . . . . . . . . . . . . . . . .   Test\n");

        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Delete Group Suite                                                    //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Delete Group  . . . . . . . . . . . . . . . . . . . .   Suite\n");

        printf("      Delete Normal Group . . . . . . . . . . . . . . . . .     ");

        //
        // This group was created in pass #1
        //

        RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamLookupNamesInDomain(
                       DomainHandle,
                       1,
                       &AccountNames[0],
                       &LookedUpRids,
                       &LookedUpUses
                       );
        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(LookedUpUses[0] == SidTypeGroup);
        RtlFreeUnicodeString( &AccountNames[0] );



        GroupHandle1 = NULL;

        NtStatus = SamOpenGroup( DomainHandle, DELETE, LookedUpRids[0], &GroupHandle1 );
        TST_SUCCESS_ASSERT(NtStatus);
        SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );

        NtStatus = SamDeleteGroup( GroupHandle1 );
        if (NT_SUCCESS(NtStatus)) {
            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }




        printf("      Delete Well Known Group . . . . . . . . . . . . . . .     ");

        GroupHandle1 = NULL;

        NtStatus = SamOpenGroup( DomainHandle, DELETE, DOMAIN_GROUP_RID_USERS, &GroupHandle1 );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamDeleteGroup( GroupHandle1 );
        if (NtStatus == STATUS_SPECIAL_ACCOUNT) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }

        NtStatus = SamCloseHandle( GroupHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));








        printf("      Delete Primary Group Of A User. . . . . . . . . . . .     ");

        //
        // Make a user (might already exist)
        // Make a group
        // Make the group the user's primary group
        // Attempt to delete the group
        // Change the user so the group isn't the primary group
        // delete the group
        // If we created the user, delete it.

        //
        // The following user might already exist (from earlier in the test)
        //

        RtlInitString( &AccountNameAnsi, USER_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );


        UserRid = 0;
        UserHandle1 = NULL;
        NtStatus = SamCreateUserInDomain(
                       DomainHandle,
                       &AccountName,
                       USER_ALL_ACCESS,
                       &UserHandle1,
                       &UserRid
                       );
        RtlFreeUnicodeString( &AccountName );
        DeleteUser = TRUE;
        if (NtStatus == STATUS_USER_EXISTS) {
            DeleteUser = FALSE;
            RtlInitString( &AccountNameAnsi, USER_NAME1 );
            NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
            TST_SUCCESS_ASSERT(NtStatus);

            NtStatus = SamLookupNamesInDomain(
                           DomainHandle,
                           1,
                           &AccountNames[0],
                           &LookedUpRids,
                           &LookedUpUses
                           );
            RtlFreeUnicodeString( &AccountNames[0] );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(LookedUpUses[0] == SidTypeUser);
            UserRid = LookedUpRids[0];
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_ALL_ACCESS,
                           UserRid,
                           &UserHandle1);
            SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );
        }

        ASSERT(NT_SUCCESS(NtStatus));

        //
        // create the group
        //

        RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );

        GroupRid = 0;
        GroupHandle1 = NULL;
        NtStatus = SamCreateGroupInDomain(
                       DomainHandle,
                       &AccountName,
                       GROUP_ALL_ACCESS,
                       &GroupHandle1,
                       &GroupRid
                       );
        RtlFreeUnicodeString( &AccountName );
        ASSERT(NT_SUCCESS(NtStatus));

        //
        // Make the user a member of this group
        //

        NtStatus = SamAddMemberToGroup(
                       GroupHandle1,
                       UserRid,
                       SE_GROUP_MANDATORY              |
                           SE_GROUP_ENABLED_BY_DEFAULT |
                           SE_GROUP_ENABLED
                       );
        ASSERT(NT_SUCCESS(NtStatus));




        //
        // Now try to delete the group
        //

        NtStatus = SamDeleteGroup( GroupHandle1 );
        if (NtStatus == STATUS_MEMBER_IN_GROUP) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        //
        // Now get rid of the group and possibly the user account
        //

        NtStatus = SamRemoveMemberFromGroup(GroupHandle1, UserRid);
        ASSERT(NT_SUCCESS(NtStatus));


        NtStatus = SamDeleteGroup( GroupHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));

        if (DeleteUser == TRUE) {
            NtStatus = SamDeleteUser( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        } else {
            NtStatus = SamCloseHandle( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        }



        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Add/Remove Member Suite                                               //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Add/Remove Member Suite . . . . . . . . . . . . . . .   Suite\n");

        printf("      Add Member  . . . . . . . . . . . . . . . . . . . . .     ");

        //
        // This test sets things up for the next test
        //

        //
        // The following user might already exist (from earlier in the test)
        //

        RtlInitString( &AccountNameAnsi, USER_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );

        UserRid = 0;
        UserHandle1 = NULL;
        NtStatus = SamCreateUserInDomain(
                       DomainHandle,
                       &AccountName,
                       USER_ALL_ACCESS,
                       &UserHandle1,
                       &UserRid
                       );
        RtlFreeUnicodeString( &AccountName );
        DeleteUser = TRUE;
        if (NtStatus == STATUS_USER_EXISTS) {
            DeleteUser = FALSE;
            RtlInitString( &AccountNameAnsi, USER_NAME1 );
            NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
            TST_SUCCESS_ASSERT(NtStatus);

            NtStatus = SamLookupNamesInDomain(
                           DomainHandle,
                           1,
                           &AccountNames[0],
                           &LookedUpRids,
                           &LookedUpUses
                           );
            RtlFreeUnicodeString( &AccountNames[0] );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(LookedUpUses[0] == SidTypeUser);
            UserRid = LookedUpRids[0];
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_ALL_ACCESS,
                           UserRid,
                           &UserHandle1);
            SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );
        }

        ASSERT(NT_SUCCESS(NtStatus));


        //
        // create the group
        //

        RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );

        GroupRid = 0;
        GroupHandle1 = NULL;
        NtStatus = SamCreateGroupInDomain(
                       DomainHandle,
                       &AccountName,
                       GROUP_ALL_ACCESS,
                       &GroupHandle1,
                       &GroupRid
                       );
        RtlFreeUnicodeString( &AccountName );
        ASSERT(NT_SUCCESS(NtStatus));

        //
        // Make the user a member of this group
        //

        NtStatus = SamAddMemberToGroup(
                       GroupHandle1,
                       UserRid,
                       SE_GROUP_MANDATORY              |
                           SE_GROUP_ENABLED_BY_DEFAULT |
                           SE_GROUP_ENABLED
                       );

        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInGroup(
                           GroupHandle1,
                           &Members,
                           &Attributes,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            NtStatus = STATUS_MEMBER_NOT_IN_GROUP;
            for ( i=0; i<MemberCount; i++) {
                if (Members[i] == UserRid) {
                    NtStatus = STATUS_SUCCESS;
                    break;
                }
            }

            if (NT_SUCCESS(NtStatus)) {
                if (Attributes[i] == SE_GROUP_MANDATORY          |
                                           SE_GROUP_ENABLED_BY_DEFAULT |
                                           SE_GROUP_ENABLED) {
                    printf("Succeeded\n");
                } else {
                    printf("Failed\n");
                    printf("Member Added but attributes don't match expected value.\n");
                    printf("Expected value:  0x%lx\n",(SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED));
                    printf("Retrieved value:  0x%lx\n",Attributes[i]);
                    TestStatus = FALSE;
                }
            } else {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user not in member list for group.\n");
                TestStatus = FALSE;
            }


            if (Members != NULL) {
                SamFreeMemory( Members );
                SamFreeMemory( Attributes );
            }


        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }




        printf("      Remove Member . . . . . . . . . . . . . . . . . . . .     ");

        //
        // The previous test sets this one up.
        //

        //
        // Now try to remove the user from the group
        //

        NtStatus = SamRemoveMemberFromGroup(GroupHandle1, UserRid);
        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInGroup(
                           GroupHandle1,
                           &Members,
                           &Attributes,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            for ( i=0; i<MemberCount; i++) {
                if (Members[i] == UserRid) {
                    NtStatus = STATUS_MEMBER_IN_GROUP;
                    break;
                }
            }

            if (NT_SUCCESS(NtStatus)) {
                printf("Succeeded\n");
            } else {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user still in member list for group.\n");
                TestStatus = FALSE;
            }


            SamFreeMemory( Members );
            SamFreeMemory( Attributes );

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        //
        // and clean up the user and group accounts
        //

        NtStatus = SamDeleteGroup( GroupHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));

        if (DeleteUser == TRUE) {
            NtStatus = SamDeleteUser( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        } else {
            NtStatus = SamCloseHandle( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        }






        printf("      Add Non-Existant Member . . . . . . . . . . . . . . .     ");

        //
        // create the group
        //

        RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );

        GroupRid = 0;
        GroupHandle1 = NULL;
        NtStatus = SamCreateGroupInDomain(
                       DomainHandle,
                       &AccountName,
                       GROUP_ALL_ACCESS,
                       &GroupHandle1,
                       &GroupRid
                       );
        RtlFreeUnicodeString( &AccountName );
        ASSERT(NT_SUCCESS(NtStatus));

        //
        // Specify a non-existant user be added to this group
        //

        UserRid = 30732579;             // Pretty sure this user doesn't exist.
        NtStatus = SamAddMemberToGroup(
                       GroupHandle1,
                       UserRid,
                       SE_GROUP_MANDATORY              |
                           SE_GROUP_ENABLED_BY_DEFAULT |
                           SE_GROUP_ENABLED
                       );

        if (NtStatus == STATUS_NO_SUCH_USER) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        NtStatus = SamDeleteGroup( GroupHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));




        printf("      Remove Non-existant Member  . . . . . . . . . . . . .     ");

        //
        // create the group
        //

        RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );

        GroupRid = 0;
        GroupHandle1 = NULL;
        NtStatus = SamCreateGroupInDomain(
                       DomainHandle,
                       &AccountName,
                       GROUP_ALL_ACCESS,
                       &GroupHandle1,
                       &GroupRid
                       );
        RtlFreeUnicodeString( &AccountName );
        ASSERT(NT_SUCCESS(NtStatus));

        //
        // Specify a non-existant user be removed from this group
        //

        UserRid = 30732579;             // Pretty sure this user doesn't exist.
        NtStatus = SamRemoveMemberFromGroup( GroupHandle1, UserRid );

        if (NtStatus == STATUS_NO_SUCH_USER) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        NtStatus = SamDeleteGroup( GroupHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));




        printf("      Remove Primary Group Of Member  . . . . . . . . . . .     ");


        //
        // Make a user (might already exist)
        // Make a group
        // Make the group the user's primary group
        // Attempt to remove the group (should fail)
        // Change the user so the group isn't the primary group
        // remove the group
        // delete the group
        // If we created the user, delete it.

        //
        // The following user might already exist (from earlier in the test)
        //

        RtlInitString( &AccountNameAnsi, USER_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );

        UserRid = 0;
        UserHandle1 = NULL;
        NtStatus = SamCreateUserInDomain(
                       DomainHandle,
                       &AccountName,
                       USER_ALL_ACCESS,
                       &UserHandle1,
                       &UserRid
                       );
        RtlFreeUnicodeString( &AccountName );
        DeleteUser = TRUE;
        if (NtStatus == STATUS_USER_EXISTS) {
            DeleteUser = FALSE;
            RtlInitString( &AccountNameAnsi, USER_NAME1 );
            NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
            TST_SUCCESS_ASSERT(NtStatus);

            NtStatus = SamLookupNamesInDomain(
                           DomainHandle,
                           1,
                           &AccountNames[0],
                           &LookedUpRids,
                           &LookedUpUses
                           );
            RtlFreeUnicodeString( &AccountNames[0] );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(LookedUpUses[0] == SidTypeUser);
            UserRid = LookedUpRids[0];
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_ALL_ACCESS,
                           UserRid,
                           &UserHandle1);
            SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );
        }

        ASSERT(NT_SUCCESS(NtStatus));


        //
        // create the group
        //

        RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );

        GroupRid = 0;
        GroupHandle1 = NULL;
        NtStatus = SamCreateGroupInDomain(
                       DomainHandle,
                       &AccountName,
                       GROUP_ALL_ACCESS,
                       &GroupHandle1,
                       &GroupRid
                       );
        RtlFreeUnicodeString( &AccountName );
        ASSERT(NT_SUCCESS(NtStatus));

        //
        // Make the user a member of this group
        //

        NtStatus = SamAddMemberToGroup(
                       GroupHandle1,
                       UserRid,
                       SE_GROUP_MANDATORY              |
                           SE_GROUP_ENABLED_BY_DEFAULT |
                           SE_GROUP_ENABLED
                       );
        ASSERT(NT_SUCCESS(NtStatus));


        //
        // Set the user's primary group Id to be this group
        //

        NtStatus = SamSetInformationUser(
                       UserHandle1,
                       UserPrimaryGroupInformation,
                       &GroupRid
                       );
        ASSERT(NT_SUCCESS(NtStatus));



        //
        // Now try to remove the user from the group
        //

        NtStatus = SamRemoveMemberFromGroup(GroupHandle1, UserRid);
        if (NtStatus == STATUS_MEMBERS_PRIMARY_GROUP) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        //
        // Set the user's primary group Id back and remove the user
        // from the group
        //

        GroupRid = DOMAIN_GROUP_RID_USERS;
        NtStatus = SamSetInformationUser(
                       UserHandle1,
                       UserPrimaryGroupInformation,
                       &GroupRid
                       );
        ASSERT(NT_SUCCESS(NtStatus));
        NtStatus = SamRemoveMemberFromGroup(GroupHandle1, UserRid);
        ASSERT(NT_SUCCESS(NtStatus));



        //
        // Now get rid of the group and possibly the user account
        //


        NtStatus = SamDeleteGroup( GroupHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));

        if (DeleteUser == TRUE) {
            NtStatus = SamDeleteUser( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        } else {
            NtStatus = SamCloseHandle( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        }






        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Set Group Suite  (pass 2)                                             //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Set Group . . . . . . . . . . . . . . . . . . . . . .   Suite\n");


        printf("      Set Name  . . . . . . . . . . . . . . . . . . . . . .     ");
        printf("(Untested)\n");


        printf("      Set Name Of Well-Known Account  . . . . . . . . . . .     ");
        printf("(Untested)\n");

    }

    return(TestStatus);

}


///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Alias  Object Test Suite                                                  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////


BOOLEAN
AliasTestSuite(
    HANDLE DomainHandle,
    HANDLE BuiltinDomainHandle,
    PSID   DomainSid,
    ULONG  Pass
    )

{
    NTSTATUS            NtStatus, IgnoreStatus;
    HANDLE              AdminAliasHandle, AliasHandle1, AliasHandle2, UserHandle1, UserHandle2, UserHandle3;
    ULONG               CountReturned, i, MemberCount;
    ULONG               UserRid, UserRid2, UserRid3, AliasRid, AliasRid2;
    PVOID               Buffer, Buffer1, Buffer2;
    ULONG               NameLength;
    SAM_ENUMERATE_HANDLE EnumerationContext;
    PULONG              Members;
    PSID                *AliasMembers;
    PSID_NAME_USE       LookedUpUses;
    PULONG              LookedUpRids;
    UNICODE_STRING      AccountNames[10], AccountName;
    STRING              AccountNameAnsi;
    PSID                UserSid1, UserSid2, GroupSid;

    BOOLEAN             IndividualTestSucceeded, DeleteUser;
    BOOLEAN             TestStatus = TRUE;


    if (Pass == 1) {
        //
        // This test suite assumes that lookup and enumeration API funciton
        // properly.
        //

        printf("\n");
        printf("\n");
        printf("  Alias (Pass #1) . . . . . . . . . . . . . . . . . . .   Test\n");

        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Open Alias Suite                                                      //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("    Open Alias  . . . . . . . . . . . . . . . . . . . . .   Suite\n");
        printf("      Open Aliases . . . . . . . . . . . . . . . . . . . . .     ");
        IndividualTestSucceeded = TRUE;
        EnumerationContext = 0;
        NtStatus = SamEnumerateAliasesInDomain(
                       DomainHandle,
                       &EnumerationContext,
                       &Buffer,
                       12000,                   // PreferedMaximumLength
                       &CountReturned
                       );

        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(Buffer != NULL);
        ASSERT(CountReturned > 0);

        for (i=0; i<CountReturned; i++) {

            NtStatus = SamOpenAlias(
                           DomainHandle,
                           ALIAS_ALL_ACCESS,
                           ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId,
                           &AliasHandle1
                           );

            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamOpenAlias(
                               DomainHandle,
                               GENERIC_READ,
                               ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId,
                               &AliasHandle2
                               );

                if (NT_SUCCESS(NtStatus)) {
                    IgnoreStatus = SamCloseHandle( AliasHandle2 );
                    ASSERT( NT_SUCCESS(IgnoreStatus) );
                } else {
                    printf("Failed\n");
                    printf("        Completion status is 0x%lx\n", NtStatus);
                    printf("        Failed opening alias second time.\n");
                    printf("        Rid of account is:   0x%lx\n",
                        ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId);
                    printf("        Name of account is:  %wZ\n",
                        &((PSAM_RID_ENUMERATION)(Buffer))[i].Name );
                    TestStatus = FALSE;
                    IndividualTestSucceeded = FALSE;
                }

                IgnoreStatus = SamCloseHandle( AliasHandle1 );
                ASSERT( NT_SUCCESS(IgnoreStatus) );

            } else {

                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                printf("        Failed opening alias for first time.\n");
                printf("        Rid of account is:   0x%lx\n",
                    ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId);
                printf("        Name of account is:  %wZ\n",
                    &((PSAM_RID_ENUMERATION)(Buffer))[i].Name );
                TestStatus = FALSE;
                IndividualTestSucceeded = FALSE;
            }

            if (!IndividualTestSucceeded) {
                printf("                                                                ");
            }
        }


        SamFreeMemory( Buffer );
        if (IndividualTestSucceeded) {
            printf("Succeeded\n");
        }



        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Query     Alias Suite                                                 //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////


        //
        // Get the rid of an alias created earlier in the test
        //

        RtlInitString( &AccountNameAnsi, ALIAS_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamLookupNamesInDomain(
                       DomainHandle,
                       1,
                       &AccountNames[0],
                       &LookedUpRids,
                       &LookedUpUses
                       );
        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(LookedUpUses[0] == SidTypeAlias);
        RtlFreeUnicodeString( &AccountNames[0] );

        AliasRid = LookedUpRids[0];

        SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );


        printf("\n");
        printf("    Query Alias . . . . . . . . . . . . . . . . . . . . .   Suite\n");

        printf("      Query Alias General Information . . . . . . . . . . .     ");


        NtStatus = SamOpenAlias(
                       DomainHandle,
                       ALIAS_READ_INFORMATION,
                       AliasRid,
                       &AliasHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationAlias(
                       AliasHandle1,
                       AliasGeneralInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((ALIAS_GENERAL_INFORMATION *)Buffer)->Name.MaximumLength > 0) &&
                     (((ALIAS_GENERAL_INFORMATION *)Buffer)->Name.Buffer != NULL)  ) {

                    printf("Succeeded\n");

                    printf("        Member Count is:  0x%lx\n",
                     (((ALIAS_GENERAL_INFORMATION *)Buffer)->MemberCount) );
                    printf("        Alias Name is:    %wZ\n",
                     &(((ALIAS_GENERAL_INFORMATION *)Buffer)->Name) );

                } else {
                    printf("Failed\n");
                    printf("        Alias Name not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( AliasHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query Alias Name Information  . . . . . . . . . . . .     ");


        NtStatus = SamOpenAlias(
                       DomainHandle,
                       ALIAS_READ_INFORMATION,
                       AliasRid,
                       &AliasHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationAlias(
                       AliasHandle1,
                       AliasNameInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((ALIAS_NAME_INFORMATION *)Buffer)->Name.MaximumLength > 0) &&
                     (((ALIAS_NAME_INFORMATION *)Buffer)->Name.Buffer != NULL)  ) {

                    printf("Succeeded\n");

                    printf("        Alias Name is:    %wZ\n",
                     &(((ALIAS_NAME_INFORMATION *)Buffer)->Name) );
                } else {
                    printf("Failed\n");
                    printf("        Alias Name not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( AliasHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query Alias Admin Comment Information . . . . . . . .     ");


        NtStatus = SamOpenAlias(
                       DomainHandle,
                       ALIAS_READ_INFORMATION,
                       AliasRid,
                       &AliasHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationAlias(
                       AliasHandle1,
                       AliasAdminCommentInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((ALIAS_ADM_COMMENT_INFORMATION *)Buffer)->AdminComment.MaximumLength >= 0) ) {

                    printf("Succeeded\n");

                    printf("        Alias Admin Comment is:    %wZ\n",
                     &(((ALIAS_ADM_COMMENT_INFORMATION *)Buffer)->AdminComment) );
                } else {
                    printf("Failed\n");
                    printf("        Alias Admin Comment not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( AliasHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );





        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Get Members Of Alias Suite                                            //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Get Members . . . . . . . . . . . . . . . . . . . . .   Suite\n");

#ifdef LATER // ALIAS_LATER - well-know aliases ?


        davidc/chads - this needs to access the builtin domain.

        printf("      Get Members of Well-Known Account . . . . . . . . . .     ");

        NtStatus = SamOpenAlias(
                       DomainHandle,
                       ALIAS_LIST_MEMBERS,
                       DOMAIN_ALIAS_RID_ADMINS,
                       &AliasHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamGetMembersInAlias(
                       AliasHandle1,
                       &AliasMembers,
                       &Attributes,
                       &MemberCount
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Members != NULL || Attributes != NULL) {

                printf("Succeeded\n");


                printf("       Member Count:    %d Users\n", MemberCount);
                for ( i=0; i<MemberCount; i++) {

                    // printf("       User[%d] Sid:      0x%lx\n",
                    //    i, Members[i]);


                }

                SamFreeMemory( AliasMembers );
                SamFreeMemory( Attributes );


            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( AliasHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );
#endif


        printf("      Get Members of Empty Alias. . . . . . . . . . . . . .     ");

        //
        // This alias was created earlier in the test
        //

        RtlInitString( &AccountNameAnsi, ALIAS_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamLookupNamesInDomain(
                       DomainHandle,
                       1,
                       &AccountNames[0],
                       &LookedUpRids,
                       &LookedUpUses
                       );
        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(LookedUpUses[0] == SidTypeAlias);
        RtlFreeUnicodeString( &AccountNames[0] );



        AliasHandle1 = NULL;

        NtStatus = SamOpenAlias( DomainHandle, ALIAS_LIST_MEMBERS, LookedUpRids[0], &AliasHandle1 );
        TST_SUCCESS_ASSERT(NtStatus);
        SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );

        NtStatus = SamGetMembersInAlias(
                       AliasHandle1,
                       &AliasMembers,
                       &MemberCount
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (MemberCount == 0) {

                printf("Succeeded\n");




            } else {
                printf("Failed\n");
                printf("       Member Count > 0 :    %d\n", MemberCount);
                for ( i=0; i<MemberCount; i++) {

                    // printf("       User[%d] Rid/Attributes:      0x%lx/0x%lx\n",
                    //    i, Members[i], Attributes[i]);
                }

                SamFreeMemory( AliasMembers );
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( AliasHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );



        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Set Alias Suite  (pass 1)                                             //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Set Alias . . . . . . . . . . . . . . . . . . . . . .   Suite\n");
        //


        // Get the rid of an alias created earlier in the test
        //

        RtlInitString( &AccountNameAnsi, ALIAS_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamLookupNamesInDomain(
                       DomainHandle,
                       1,
                       &AccountNames[0],
                       &LookedUpRids,
                       &LookedUpUses
                       );
        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(LookedUpUses[0] == SidTypeAlias);
        RtlFreeUnicodeString( &AccountNames[0] );

        AliasRid = LookedUpRids[0];

        SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );



        printf("      Set Admin Comment . . . . . . . . . . . . . . . . . .     ");

        NtStatus = SamOpenAlias(
                       DomainHandle,
                       ALIAS_WRITE_ACCOUNT | ALIAS_READ_INFORMATION,
                       AliasRid,
                       &AliasHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        //
        // Get the current value...
        //

        Buffer1 = NULL;
        NtStatus = SamQueryInformationAlias(
                       AliasHandle1,
                       AliasAdminCommentInformation,
                       &Buffer1
                       );
        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(Buffer1 != NULL);


        //
        // Change the field to a new value and write it out.
        //

        NameLength = ((ALIAS_ADM_COMMENT_INFORMATION *)Buffer1)->AdminComment.Length;
        if (  NameLength == DummyString1.Length ) {
            ((ALIAS_ADM_COMMENT_INFORMATION *)Buffer1)->AdminComment = DummyString2;
        } else {
            ((ALIAS_ADM_COMMENT_INFORMATION *)Buffer1)->AdminComment = DummyString1;
        }

        NtStatus = SamSetInformationAlias(
                       AliasHandle1,
                       AliasAdminCommentInformation,
                       Buffer1
                       );
        if ( NT_SUCCESS(NtStatus) ) {

            //
            // Now check that the change was really made...
            //

            Buffer2 = NULL;
            NtStatus = SamQueryInformationAlias(
                           AliasHandle1,
                           AliasAdminCommentInformation,
                           &Buffer2
                           );
            ASSERT(NT_SUCCESS( NtStatus ) );
            if (
                !RtlCompareString(
                    (PSTRING)&((ALIAS_ADM_COMMENT_INFORMATION *)Buffer1)->AdminComment,
                    (PSTRING)&((ALIAS_ADM_COMMENT_INFORMATION *)Buffer2)->AdminComment,
                    TRUE)
                ) {

                printf("Succeeded\n");

            } else {

                printf("Failed\n");
                printf("        Value queried doesn't match value written\n");
                printf("        Value Written is   %wZ\n",
                    (PUNICODE_STRING)&((ALIAS_ADM_COMMENT_INFORMATION *)Buffer1)->AdminComment);
                printf("        Value Retrieved is %wZ\n",
                    (PUNICODE_STRING)&((ALIAS_ADM_COMMENT_INFORMATION *)Buffer2)->AdminComment);

                TestStatus = FALSE;

            }

            SamFreeMemory( Buffer1 );
            SamFreeMemory( Buffer2 );

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
            SamFreeMemory( Buffer1 );

        }





    } // END PASS #1
    if (Pass == 2) {

        printf("\n");
        printf("\n");
        printf("  Alias (Pass #2) . . . . . . . . . . . . . . . . . . .   Test\n");

        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Delete Alias Suite                                                    //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Delete Alias  . . . . . . . . . . . . . . . . . . . .   Suite\n");

        printf("      Delete Normal Alias . . . . . . . . . . . . . . . . .     ");

        //
        // This alias was created in pass #1
        //

        RtlInitString( &AccountNameAnsi, ALIAS_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamLookupNamesInDomain(
                       DomainHandle,
                       1,
                       &AccountNames[0],
                       &LookedUpRids,
                       &LookedUpUses
                       );
        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(LookedUpUses[0] == SidTypeAlias);
        RtlFreeUnicodeString( &AccountNames[0] );



        AliasHandle1 = NULL;

        NtStatus = SamOpenAlias( DomainHandle, DELETE, LookedUpRids[0], &AliasHandle1 );
        TST_SUCCESS_ASSERT(NtStatus);
        SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );

        NtStatus = SamDeleteAlias( AliasHandle1 );
        if (NT_SUCCESS(NtStatus)) {
            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


#ifdef LATER // ALIAS_LATER - well know aliases ?


        printf("      Delete Well Known Alias . . . . . . . . . . . . . . .     ");

        AliasHandle1 = NULL;

        NtStatus = SamOpenAlias( DomainHandle, DELETE, DOMAIN_GROUP_RID_USERS, &AliasHandle1 );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamDeleteAlias( AliasHandle1 );
        if (NtStatus == STATUS_SPECIAL_ACCOUNT) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }

        NtStatus = SamCloseHandle( AliasHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));




        printf("      Delete Admin Alias. . . . . . . . . . . . . . . . . .     ");
        AliasHandle1 = NULL;

        NtStatus = SamOpenAlias( DomainHandle, DELETE, DOMAIN_ALIAS_RID_ADMINS, &AliasHandle1 );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamDeleteAlias( AliasHandle1 );
        if (NtStatus == STATUS_SPECIAL_ACCOUNT) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }

        NtStatus = SamCloseHandle( AliasHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));


#endif



        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Add/Remove Member Suite                                               //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Add/Remove Member Suite . . . . . . . . . . . . . . .   Suite\n");

        printf("      Add Member  . . . . . . . . . . . . . . . . . . . . .     ");

        //
        // This test sets things up for the next test
        //

        //
        // The following user might already exist (from earlier in the test)
        //

        RtlInitString( &AccountNameAnsi, USER_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        UserRid = 0;
        UserHandle1 = NULL;
        NtStatus = SamCreateUserInDomain(
                       DomainHandle,
                       &AccountName,
                       USER_ALL_ACCESS,
                       &UserHandle1,
                       &UserRid
                       );
        RtlFreeUnicodeString( &AccountName );
        DeleteUser = TRUE;
        if (NtStatus == STATUS_USER_EXISTS) {
            DeleteUser = FALSE;
            RtlInitString( &AccountNameAnsi, USER_NAME1 );
            NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
            TST_SUCCESS_ASSERT(NtStatus);

            NtStatus = SamLookupNamesInDomain(
                           DomainHandle,
                           1,
                           &AccountNames[0],
                           &LookedUpRids,
                           &LookedUpUses
                           );
            RtlFreeUnicodeString( &AccountNames[0] );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(LookedUpUses[0] == SidTypeUser);
            UserRid = LookedUpRids[0];
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_ALL_ACCESS,
                           UserRid,
                           &UserHandle1);
            SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );
        }

        ASSERT(NT_SUCCESS(NtStatus));

        //
        // This account won't exist yet
        //

        RtlInitString( &AccountNameAnsi, USER_NAME2 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        UserRid2 = 0;
        UserHandle2 = NULL;
        NtStatus = SamCreateUserInDomain(
                       DomainHandle,
                       &AccountName,
                       USER_ALL_ACCESS,
                       &UserHandle2,
                       &UserRid2
                       );
        RtlFreeUnicodeString( &AccountName );

        ASSERT(NT_SUCCESS(NtStatus));


        //
        // create the alias
        //

        RtlInitString( &AccountNameAnsi, ALIAS_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        AliasRid = 0;
        AliasHandle1 = NULL;
        NtStatus = SamCreateAliasInDomain(
                       DomainHandle,
                       &AccountName,
                       ALIAS_ALL_ACCESS,
                       &AliasHandle1,
                       &AliasRid
                       );
        RtlFreeUnicodeString( &AccountName );
        ASSERT(NT_SUCCESS(NtStatus));

        //
        // Make user1 a member of this alias
        //

        UserSid1 = CreateUserSid(DomainSid, UserRid);
        ASSERT(UserSid1 != NULL);

        UserSid2 = CreateUserSid(DomainSid, UserRid2);
        ASSERT(UserSid2 != NULL);



        NtStatus = SamAddMemberToAlias(
                       AliasHandle1,
                       UserSid1
                       );

        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInAlias(
                           AliasHandle1,
                           &AliasMembers,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
            for ( i=0; i<MemberCount; i++) {
                if (RtlEqualSid(AliasMembers[i], UserSid1)) {
                    NtStatus = STATUS_SUCCESS;
                    break;
                }
            }

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user not in member list for alias.\n");
                printf("Member list :\n");
                for (i=0; i<MemberCount; i++) {
                    printfSid(AliasMembers[i]);
                    printf("\n");
                }
                DebugBreak();
                TestStatus = FALSE;
            }


            if (AliasMembers != NULL) {
                SamFreeMemory( AliasMembers );
            }


            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamGetAliasMembership(
                               DomainHandle,
                               1,
                               &UserSid1,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
                for ( i=0; i<MemberCount; i++) {
                    if (Members[i] == AliasRid) {
                        NtStatus = STATUS_SUCCESS;
                        break;
                    }
                }

                if (!NT_SUCCESS(NtStatus)) {
                    printf("Failed\n");
                    printf("Service returned SUCCESS, but alias not in account alias membership list.\n");
                    printf("Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }


                //
                // Check for correct alias membership for multiple accounts
                // User1 should be in alias1
                // User2 should be no aliases.
                //

                if (NT_SUCCESS(NtStatus)) {

                    PSID    SidArray[2];
                    SidArray[0] = UserSid1;
                    SidArray[1] = UserSid2;

                    NtStatus = SamGetAliasMembership(
                                   DomainHandle,
                                   2,
                                   SidArray,
                                   &MemberCount,
                                   &Members
                                   );
                    ASSERT(NT_SUCCESS(NtStatus));

                    if (MemberCount != 1) {

                        printf("Failed\n");
                        printf("Service returned SUCCESS, but combined alias membership count for 2 accounts not correct.\n");
                        printf("Combined Alias Membership :\n");
                        for (i=0; i<MemberCount; i++) {
                            printf("0x%lx\n", Members[i]);
                        }
                        DebugBreak();
                        TestStatus = FALSE;

                    } else {

                        if (Members[0] != AliasRid) {
                            printf("Failed\n");
                            printf("Service returned SUCCESS, but combined alias membership for 2 accounts not correct.\n");
                            printf("Combined Alias Membership :\n");
                            for (i=0; i<MemberCount; i++) {
                                printf("0x%lx\n", Members[i]);
                            }
                            DebugBreak();
                            TestStatus = FALSE;

                        } else {
                            printf("Succeeded\n");
                        }
                    }

                    if (Members != NULL) {
                        SamFreeMemory( Members );
                    }
                }
            }


        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }







        printf("      Add another member to another alias . . . . . . . . .     ");






        //
        // Make user2 a member of alias2
        //

        //
        // This alias was created in pass #1
        //

        RtlInitString( &AccountNameAnsi, ALIAS_NAME2 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamLookupNamesInDomain(
                       DomainHandle,
                       1,
                       &AccountNames[0],
                       &LookedUpRids,
                       &LookedUpUses
                       );
        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(LookedUpUses[0] == SidTypeAlias);
        RtlFreeUnicodeString( &AccountNames[0] );

        AliasHandle2 = NULL;
        AliasRid2 = LookedUpRids[0];

        NtStatus = SamOpenAlias( DomainHandle, ALIAS_ALL_ACCESS, LookedUpRids[0], &AliasHandle2 );
        TST_SUCCESS_ASSERT(NtStatus);
        SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );


        NtStatus = SamAddMemberToAlias(
                       AliasHandle2,
                       UserSid2
                       );

        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInAlias(
                           AliasHandle2,
                           &AliasMembers,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
            for ( i=0; i<MemberCount; i++) {
                if (RtlEqualSid(AliasMembers[i], UserSid2)) {
                    NtStatus = STATUS_SUCCESS;
                    break;
                }
            }

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user not in member list for alias.\n");
                printf("Member list :\n");
                for (i=0; i<MemberCount; i++) {
                    printfSid(AliasMembers[i]);
                    printf("\n");
                }
                DebugBreak();
                TestStatus = FALSE;
            }


            if (AliasMembers != NULL) {
                SamFreeMemory( AliasMembers );
            }


            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamGetAliasMembership(
                               DomainHandle,
                               1,
                               &UserSid2,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
                for ( i=0; i<MemberCount; i++) {
                    if (Members[i] == AliasRid2) {
                        NtStatus = STATUS_SUCCESS;
                        break;
                    }
                }

                if (!NT_SUCCESS(NtStatus)) {
                    printf("Failed\n");
                    printf("Service returned SUCCESS, but alias not in account alias membership list.\n");
                    printf("Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }

                //
                // Check for correct alias membership for multiple accounts
                // User1 should be in alias1
                // User2 should be in alias2.
                //

                if (NT_SUCCESS(NtStatus)) {

                    PSID    SidArray[2];
                    SidArray[0] = UserSid1;
                    SidArray[1] = UserSid2;

                    NtStatus = SamGetAliasMembership(
                                   DomainHandle,
                                   2,
                                   SidArray,
                                   &MemberCount,
                                   &Members
                                   );
                    ASSERT(NT_SUCCESS(NtStatus));

                    if (MemberCount != 2) {

                        printf("Failed\n");
                        printf("Service returned SUCCESS, but combined alias membership count for 2 accounts not correct.\n");
                        printf("Combined Alias Membership :\n");
                        for (i=0; i<MemberCount; i++) {
                            printf("0x%lx\n", Members[i]);
                        }
                        DebugBreak();
                        TestStatus = FALSE;

                    } else {

                        if (((Members[0] == AliasRid) && (Members[1] == AliasRid2)) ||
                            ((Members[0] == AliasRid2) && (Members[1] == AliasRid)) ) {
                            printf("Succeeded\n");
                        } else {
                            printf("Failed\n");
                            printf("Service returned SUCCESS, but combined alias membership for 2 accounts not correct.\n");
                            printf("Combined Alias Membership :\n");
                            for (i=0; i<MemberCount; i++) {
                                printf("0x%lx\n", Members[i]);
                            }
                            DebugBreak();
                            TestStatus = FALSE;
                        }
                    }

                    if (Members != NULL) {
                        SamFreeMemory( Members );
                    }
                }
            }


        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        //
        // Remove user2 from alias2 again
        //

        NtStatus = SamRemoveMemberFromAlias(
                       AliasHandle2,
                       UserSid2
                       );

        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInAlias(
                           AliasHandle2,
                           &AliasMembers,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
            for ( i=0; i<MemberCount; i++) {
                if (RtlEqualSid(AliasMembers[i], UserSid2)) {
                    NtStatus = STATUS_SUCCESS;
                    break;
                }
            }

            if (NtStatus != STATUS_MEMBER_NOT_IN_ALIAS) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user still in member list for alias.\n");
                printf("Member list :\n");
                for (i=0; i<MemberCount; i++) {
                    printfSid(AliasMembers[i]);
                    printf("\n");
                }
                DebugBreak();
                TestStatus = FALSE;
            }


            if (AliasMembers != NULL) {
                SamFreeMemory( AliasMembers );
            }


            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamGetAliasMembership(
                               DomainHandle,
                               1,
                               &UserSid2,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                for ( i=0; i<MemberCount; i++) {
                    if (Members[i] == AliasRid2) {
                        NtStatus = STATUS_MEMBER_IN_ALIAS;
                        break;
                    }
                }

                if (!NT_SUCCESS(NtStatus)) {
                    printf("Failed\n");
                    printf("Service returned SUCCESS, but alias still in account alias membership list.\n");
                    printf("Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }

                //
                // Check for correct alias membership for multiple accounts
                // User1 should be in alias1
                // User2 should be in no aliases.
                //

                if (NT_SUCCESS(NtStatus)) {

                    PSID    SidArray[2];
                    SidArray[0] = UserSid1;
                    SidArray[1] = UserSid2;

                    NtStatus = SamGetAliasMembership(
                                   DomainHandle,
                                   2,
                                   SidArray,
                                   &MemberCount,
                                   &Members
                                   );
                    ASSERT(NT_SUCCESS(NtStatus));

                    if (MemberCount != 1) {

                        printf("Failed\n");
                        printf("Service returned SUCCESS, but combined alias membership count for 2 accounts not correct.\n");
                        printf("Combined Alias Membership :\n");
                        for (i=0; i<MemberCount; i++) {
                            printf("0x%lx\n", Members[i]);
                        }
                        DebugBreak();
                        TestStatus = FALSE;

                    } else {

                        if (Members[0] == AliasRid) {
                            printf("Succeeded\n");
                        } else {
                            printf("Failed\n");
                            printf("Service returned SUCCESS, but combined alias membership for 2 accounts not correct.\n");
                            printf("Combined Alias Membership :\n");
                            for (i=0; i<MemberCount; i++) {
                                printf("0x%lx\n", Members[i]);
                            }
                            DebugBreak();
                            TestStatus = FALSE;
                        }
                    }

                    if (Members != NULL) {
                        SamFreeMemory( Members );
                    }
                }
            }


        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        NtStatus = SamCloseHandle( AliasHandle2 );
        ASSERT(NT_SUCCESS(NtStatus));





        printf("      Add Another Member  . . . . . . . . . . . . . . . . .     ");


        //
        // Make user2 a member of this alias
        //

        NtStatus = SamAddMemberToAlias(
                       AliasHandle1,
                       UserSid2
                       );

        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInAlias(
                           AliasHandle1,
                           &AliasMembers,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
            for ( i=0; i<MemberCount; i++) {
                if (RtlEqualSid(AliasMembers[i], UserSid2)) {
                    NtStatus = STATUS_SUCCESS;
                    break;
                }
            }

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user not in member list for alias.\n");
                printf("Member list :\n");
                for (i=0; i<MemberCount; i++) {
                    printfSid(AliasMembers[i]);
                    printf("\n");
                }
                DebugBreak();
                TestStatus = FALSE;
            }


            if (AliasMembers != NULL) {
                SamFreeMemory( AliasMembers );
            }


            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamGetAliasMembership(
                               DomainHandle,
                               1,
                               &UserSid2,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
                for ( i=0; i<MemberCount; i++) {
                    if (Members[i] == AliasRid) {
                        NtStatus = STATUS_SUCCESS;
                        break;
                    }
                }

                if (!NT_SUCCESS(NtStatus)) {
                    printf("Failed\n");
                    printf("Service returned SUCCESS, but alias not in account alias membership list.\n");
                    printf("Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }

                //
                // Check for correct alias membership for multiple accounts
                // User1 should be in alias1
                // User2 should be in alias1.
                //

                if (NT_SUCCESS(NtStatus)) {

                    PSID    SidArray[2];
                    SidArray[0] = UserSid1;
                    SidArray[1] = UserSid2;

                    NtStatus = SamGetAliasMembership(
                                   DomainHandle,
                                   2,
                                   SidArray,
                                   &MemberCount,
                                   &Members
                                   );
                    ASSERT(NT_SUCCESS(NtStatus));

                    if (MemberCount != 1) {

                        printf("Failed\n");
                        printf("Service returned SUCCESS, but combined alias membership count for 2 accounts not correct.\n");
                        printf("Combined Alias Membership :\n");
                        for (i=0; i<MemberCount; i++) {
                            printf("0x%lx\n", Members[i]);
                        }
                        DebugBreak();
                        TestStatus = FALSE;

                    } else {

                        if (Members[0] != AliasRid) {
                            printf("Failed\n");
                            printf("Service returned SUCCESS, but combined alias membership for 2 accounts not correct.\n");
                            printf("Combined Alias Membership :\n");
                            for (i=0; i<MemberCount; i++) {
                                printf("0x%lx\n", Members[i]);
                            }
                            DebugBreak();
                            TestStatus = FALSE;

                        } else {
                            printf("Succeeded\n");
                        }
                    }

                    if (Members != NULL) {
                        SamFreeMemory( Members );
                    }
                }
            }


        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        printf("      Remove Member . . . . . . . . . . . . . . . . . . . .     ");

        //
        // The previous test sets this one up.
        //

        //
        // Now try to remove the user from the alias
        //

        NtStatus = SamRemoveMemberFromAlias(AliasHandle1, UserSid1);
        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInAlias(
                           AliasHandle1,
                           &AliasMembers,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            for ( i=0; i<MemberCount; i++) {
                if (RtlEqualSid(AliasMembers[i], UserSid1)) {
                    NtStatus = STATUS_MEMBER_IN_ALIAS;
                    break;
                }
            }

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user still in member list for alias.\n");
                printf("Member list :\n");
                for (i=0; i<MemberCount; i++) {
                    printfSid(AliasMembers[i]);
                    printf("\n");
                }
                DebugBreak();
                TestStatus = FALSE;
            }

            SamFreeMemory( AliasMembers );

            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamGetAliasMembership(
                               DomainHandle,
                               1,
                               &UserSid1,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                for ( i=0; i<MemberCount; i++) {
                    if (Members[i] == AliasRid) {
                        NtStatus = STATUS_MEMBER_IN_ALIAS;
                        break;
                    }
                }

                if (!NT_SUCCESS(NtStatus)) {
                    printf("Failed\n");
                    printf("Service returned SUCCESS, but alias still in account alias membership list.\n");
                    printf("Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }

                //
                // Check for correct alias membership for multiple accounts
                // User1 should be in no aliases
                // User2 should be in alias1.
                //

                if (NT_SUCCESS(NtStatus)) {

                    PSID    SidArray[2];
                    SidArray[0] = UserSid1;
                    SidArray[1] = UserSid2;

                    NtStatus = SamGetAliasMembership(
                                   DomainHandle,
                                   2,
                                   SidArray,
                                   &MemberCount,
                                   &Members
                                   );
                    ASSERT(NT_SUCCESS(NtStatus));

                    if (MemberCount != 1) {

                        printf("Failed\n");
                        printf("Service returned SUCCESS, but combined alias membership count for 2 accounts not correct.\n");
                        printf("Combined Alias Membership :\n");
                        for (i=0; i<MemberCount; i++) {
                            printf("0x%lx\n", Members[i]);
                        }
                        DebugBreak();
                        TestStatus = FALSE;

                    } else {

                        if (Members[0] != AliasRid) {
                            printf("Failed\n");
                            printf("Service returned SUCCESS, but combined alias membership for 2 accounts not correct.\n");
                            printf("Combined Alias Membership :\n");
                            for (i=0; i<MemberCount; i++) {
                                printf("0x%lx\n", Members[i]);
                            }
                            DebugBreak();
                            TestStatus = FALSE;

                        } else {
                            printf("Succeeded\n");
                        }
                    }

                    if (Members != NULL) {
                        SamFreeMemory( Members );
                    }
                }
            }

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }




        printf("      Add A User to ADMIN Alias . . . . . . . . . . . . . .     ");

        //
        // Make user2 a member of the ADMIN alias
        //

        NtStatus = SamOpenAlias(
                       BuiltinDomainHandle,
                       ALIAS_ALL_ACCESS,
                       DOMAIN_ALIAS_RID_ADMINS,
                       &AdminAliasHandle
                       );

        ASSERT( NT_SUCCESS( NtStatus ) );

        NtStatus = SamAddMemberToAlias(
                       AdminAliasHandle,
                       UserSid2
                       );

        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInAlias(
                           AdminAliasHandle,
                           &AliasMembers,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
            for ( i=0; i<MemberCount; i++) {
                if (RtlEqualSid(AliasMembers[i], UserSid2)) {
                    NtStatus = STATUS_SUCCESS;
                    break;
                }
            }

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user not in member list for alias.\n");
                printf("Member list :\n");
                for (i=0; i<MemberCount; i++) {
                    printfSid(AliasMembers[i]);
                    printf("\n");
                }
                DebugBreak();
                TestStatus = FALSE;
            }


            if (AliasMembers != NULL) {
                SamFreeMemory( AliasMembers );
            }


            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamGetAliasMembership(
                               BuiltinDomainHandle,
                               1,
                               &UserSid2,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
                for ( i=0; i<MemberCount; i++) {
                    if (Members[i] == DOMAIN_ALIAS_RID_ADMINS) {
                        NtStatus = STATUS_SUCCESS;
                        break;
                    }
                }

                if (!NT_SUCCESS(NtStatus)) {
                    printf("Failed\n");
                    printf("Service returned SUCCESS, but alias not in account alias membership list.\n");
                    printf("Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;

                } else {

                    printf("Succeeded\n");
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }
            }


        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        printf("      Add A Group to ADMIN Alias . . . . . . . . . . . . . .     ");

        //
        // Make a group a member of the ADMIN alias
        //

        GroupSid = CreateUserSid(DomainSid, DOMAIN_GROUP_RID_USERS );
        ASSERT(GroupSid != NULL);

        NtStatus = SamAddMemberToAlias(
                       AdminAliasHandle,
                       GroupSid
                       );

        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInAlias(
                           AdminAliasHandle,
                           &AliasMembers,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
            for ( i=0; i<MemberCount; i++) {
                if (RtlEqualSid(AliasMembers[i], GroupSid)) {
                    NtStatus = STATUS_SUCCESS;
                    break;
                }
            }

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user not in member list for alias.\n");
                printf("Member list :\n");
                for (i=0; i<MemberCount; i++) {
                    printfSid(AliasMembers[i]);
                    printf("\n");
                }
                DebugBreak();
                TestStatus = FALSE;
            }


            if (AliasMembers != NULL) {
                SamFreeMemory( AliasMembers );
            }


            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamGetAliasMembership(
                               BuiltinDomainHandle,
                               1,
                               &GroupSid,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
                for ( i=0; i<MemberCount; i++) {
                    if (Members[i] == DOMAIN_ALIAS_RID_ADMINS) {
                        NtStatus = STATUS_SUCCESS;
                        break;
                    }
                }

                if (!NT_SUCCESS(NtStatus)) {
                    printf("Failed\n");
                    printf("Service returned SUCCESS, but alias not in account alias membership list.\n");
                    printf("Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;

                } else {

                    printf("Succeeded\n");
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }
            }


        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


// NOTE: user is already created in the group below.  Should keep this
// test, AND add another with an all-new group that's been added to the ADMIN
// alias (then ADD user to group, rather than create in it).
        printf("      Create user in ADMIN ALIAS'd Group. . . . . . . . . . .     ");

        RtlInitString( &AccountNameAnsi, USER_NAME3 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        UserRid3 = 0;
        UserHandle3 = NULL;
        NtStatus = SamCreateUserInDomain(
                       DomainHandle,
                       &AccountName,
                       USER_ALL_ACCESS,
                       &UserHandle3,
                       &UserRid3
                       );
        RtlFreeUnicodeString( &AccountName );

        if ( NT_SUCCESS( NtStatus ) ) {

            printf("Succeeded\n");

        } else {

            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }



//NOTE: doesn't work because this is primary group.
//put back in when all-new group is created, above
//        printf("      Remove user from ADMIN ALIAS'd Group. . . . . . . . . . .     ");
//
//        NtStatus = SamOpenGroup(
//                       DomainHandle,
//                       GROUP_ALL_ACCESS,
//                       DOMAIN_GROUP_RID_USERS,
//                       &GroupHandle
//                       );
//
//        ASSERT(NT_SUCCESS(NtStatus));
//
//        NtStatus = SamRemoveMemberFromGroup(
//                       GroupHandle,
//                       UserRid3
//                       );
//
//        if ( NT_SUCCESS( NtStatus ) ) {
//
//            printf("Succeeded\n");
//
//        } else {
//
//            printf("Failed\n");
//            printf("        Completion status is 0x%lx\n", NtStatus);
//            TestStatus = FALSE;
//        }
//
//        IgnoreStatus = SamCloseHandle( GroupHandle );
//        ASSERT(NT_SUCCESS(IgnoreStatus));
        IgnoreStatus = SamCloseHandle( UserHandle3 );
        ASSERT(NT_SUCCESS(IgnoreStatus));



        printf("      Remove User from ADMIN alias. . . . . . . . . . .     ");

        //
        // The previous test sets this one up.
        //
        // Now try to remove the user from the alias
        //

        NtStatus = SamRemoveMemberFromAlias(AdminAliasHandle, UserSid2);
        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInAlias(
                           AdminAliasHandle,
                           &AliasMembers,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            for ( i=0; i<MemberCount; i++) {
                if (RtlEqualSid(AliasMembers[i], UserSid2)) {
                    NtStatus = STATUS_MEMBER_IN_ALIAS;
                    break;
                }
            }

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user still in member list for alias.\n");
                printf("Member list :\n");
                for (i=0; i<MemberCount; i++) {
                    printfSid(AliasMembers[i]);
                    printf("\n");
                }
                DebugBreak();
                TestStatus = FALSE;
            }

            SamFreeMemory( AliasMembers );

            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamGetAliasMembership(
                               BuiltinDomainHandle,
                               1,
                               &UserSid2,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                for ( i=0; i<MemberCount; i++) {
                    if (Members[i] == DOMAIN_ALIAS_RID_ADMINS) {
                        NtStatus = STATUS_MEMBER_IN_ALIAS;
                        break;
                    }
                }

                if (!NT_SUCCESS(NtStatus)) {
                    printf("Failed\n");
                    printf("Service returned SUCCESS, but alias still in account alias membership list.\n");
                    printf("Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;

                } else {

                    printf("Succeeded\n");
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }
            }

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }




        //
        // Make user2 a member of the ADMIN alias again, so we can test
        // the new function SamRemoveMemberFromForeignDomain().
        // NOTE: we should make this a real test item.
        //

        NtStatus = SamAddMemberToAlias(
                       AdminAliasHandle,
                       UserSid2
                       );

        ASSERT (NT_SUCCESS(NtStatus));

        NtStatus = SamRemoveMemberFromForeignDomain(
                       BuiltinDomainHandle,
                       UserSid2 );

        ASSERT (NT_SUCCESS(NtStatus));



        printf("      Remove Group from ADMIN alias. . . . . . . . . . .     ");

        //
        // The previous test sets this one up.
        //
        // Now try to remove the group from the alias
        //

        NtStatus = SamRemoveMemberFromAlias(AdminAliasHandle, GroupSid);
        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetMembersInAlias(
                           AdminAliasHandle,
                           &AliasMembers,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            for ( i=0; i<MemberCount; i++) {
                if (RtlEqualSid(AliasMembers[i], GroupSid)) {
                    NtStatus = STATUS_MEMBER_IN_ALIAS;
                    break;
                }
            }

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user still in member list for alias.\n");
                printf("Member list :\n");
                for (i=0; i<MemberCount; i++) {
                    printfSid(AliasMembers[i]);
                    printf("\n");
                }
                DebugBreak();
                TestStatus = FALSE;
            }

            SamFreeMemory( AliasMembers );

            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamGetAliasMembership(
                               BuiltinDomainHandle,
                               1,
                               &GroupSid,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                for ( i=0; i<MemberCount; i++) {
                    if (Members[i] == DOMAIN_ALIAS_RID_ADMINS) {
                        NtStatus = STATUS_MEMBER_IN_ALIAS;
                        break;
                    }
                }

                if (!NT_SUCCESS(NtStatus)) {
                    printf("Failed\n");
                    printf("Service returned SUCCESS, but alias still in account alias membership list.\n");
                    printf("Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;

                } else {

                    printf("Succeeded\n");
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }
            }

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }

        IgnoreStatus = SamCloseHandle( AdminAliasHandle );
        ASSERT( NT_SUCCESS(IgnoreStatus) );



        printf("      Delete account while member of alias. . . . . . . . .     ");


        //
        // Now delete user2 and check the alias member list is updated
        //

        NtStatus = SamDeleteUser( UserHandle2 );
        ASSERT(NT_SUCCESS(NtStatus));

        NtStatus = SamGetMembersInAlias(
                       AliasHandle1,
                       &AliasMembers,
                       &MemberCount
                       );
        ASSERT(NT_SUCCESS(NtStatus));

        for ( i=0; i<MemberCount; i++) {
            if (RtlEqualSid(AliasMembers[i], UserSid2)) {
                NtStatus = STATUS_MEMBER_IN_ALIAS;
                break;
            }
        }

        if (!NT_SUCCESS(NtStatus)) {
            printf("Failed\n");
            printf("Service returned SUCCESS, but user still in member list for alias.\n");
            printf("Member list :\n");
            for (i=0; i<MemberCount; i++) {
                printfSid(AliasMembers[i]);
                printf("\n");
            }
            DebugBreak();
            TestStatus = FALSE;
        }

        SamFreeMemory( AliasMembers );

        if (NT_SUCCESS(NtStatus)) {

            NtStatus = SamGetAliasMembership(
                           DomainHandle,
                           1,
                           &UserSid2,
                           &MemberCount,
                           &Members
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            if (MemberCount != 0) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but alias still in alias membership list for account.\n");
                printf("Alias Membership :\n");
                for (i=0; i<MemberCount; i++) {
                    printf("0x%lx\n", Members[i]);
                }
                DebugBreak();
                TestStatus = FALSE;
            }

            if (Members != NULL) {
                SamFreeMemory( Members );
            }

            //
            // Check for correct alias membership for multiple accounts
            // User1 should be in no aliases
            // User2 should be in no aliases.
            //

            if (NT_SUCCESS(NtStatus)) {

                PSID    SidArray[2];
                SidArray[0] = UserSid1;
                SidArray[1] = UserSid2;

                NtStatus = SamGetAliasMembership(
                               DomainHandle,
                               2,
                               SidArray,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                if (MemberCount != 0) {

                    printf("Failed\n");
                    printf("Service returned SUCCESS, but combined alias membership count for 2 accounts not correct.\n");
                    printf("Combined Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;

                } else {
                    printf("Succeeded\n");
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }
            }
        }




        printf("      Delete alias with members . . . . . . . . . . . . . .     ");

        //
        // Make the user a member of this alias (again)
        //

        NtStatus = SamAddMemberToAlias(
                       AliasHandle1,
                       UserSid1
                       );
        ASSERT(NT_SUCCESS(NtStatus));

        //
        // Now delete the alias and check the membership list for user is updated
        //

        NtStatus = SamDeleteAlias( AliasHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));

        NtStatus = SamGetAliasMembership(
                       DomainHandle,
                       1,
                       &UserSid1,
                       &MemberCount,
                       &Members
                       );
        ASSERT(NT_SUCCESS(NtStatus));

        for ( i=0; i<MemberCount; i++) {
            if (Members[i] == AliasRid) {
                NtStatus = STATUS_MEMBER_IN_ALIAS;
                break;
            }
        }

        if (NT_SUCCESS(NtStatus)) {
            printf("Succeeded\n");
        } else {
            printf("Failed\n");
            printf("Service returned SUCCESS, but alias still in account alias membership list.\n");
            printf("Alias Membership :\n");
            for (i=0; i<MemberCount; i++) {
                printf("0x%lx\n", Members[i]);
            }
            DebugBreak();
            TestStatus = FALSE;
        }

        if (Members != NULL) {
            SamFreeMemory( Members );
        }



        DeleteUserSid(UserSid1);
        DeleteUserSid(UserSid2);

        //
        // and clean up
        //

        if (DeleteUser == TRUE) {
            NtStatus = SamDeleteUser( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        } else {
            NtStatus = SamCloseHandle( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        }






        printf("      Add Foreign Domain Member . . . . . . . . . . . . . .     ");

        //
        // create the alias
        //

        RtlInitString( &AccountNameAnsi, ALIAS_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        AliasRid = 0;
        AliasHandle1 = NULL;
        NtStatus = SamCreateAliasInDomain(
                       DomainHandle,
                       &AccountName,
                       ALIAS_ALL_ACCESS,
                       &AliasHandle1,
                       &AliasRid
                       );
        RtlFreeUnicodeString( &AccountName );
        ASSERT(NT_SUCCESS(NtStatus));

        //
        // Specify a non-existant user be added to this alias
        //


        {
            PSID    ForeignDomainSid;

            ForeignDomainSid = CreateUserSid(DomainSid, 307333); // random domain sub-authority
            ASSERT(ForeignDomainSid != NULL);

            UserRid = 45728;    // Random user rid

            UserSid1 = CreateUserSid(ForeignDomainSid, UserRid);
            ASSERT(UserSid1 != NULL);

            DeleteUserSid(ForeignDomainSid);
        }


        NtStatus = SamAddMemberToAlias(
                       AliasHandle1,
                       UserSid1
                       );

        if (NtStatus == STATUS_SUCCESS) {

            NtStatus = SamGetMembersInAlias(
                           AliasHandle1,
                           &AliasMembers,
                           &MemberCount
                           );
            ASSERT(NT_SUCCESS(NtStatus));

            NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
            for ( i=0; i<MemberCount; i++) {
                if (RtlEqualSid(AliasMembers[i], UserSid1)) {
                    NtStatus = STATUS_SUCCESS;
                    break;
                }
            }

            if (!NT_SUCCESS(NtStatus)) {
                printf("Failed\n");
                printf("Service returned SUCCESS, but user not in member list for alias.\n");
                printf("Member list :\n");
                for (i=0; i<MemberCount; i++) {
                    printfSid(AliasMembers[i]);
                    printf("\n");
                }
                DebugBreak();
                TestStatus = FALSE;
            }


            if (AliasMembers != NULL) {
                SamFreeMemory( AliasMembers );
            }


            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamGetAliasMembership(
                               DomainHandle,
                               1,
                               &UserSid1,
                               &MemberCount,
                               &Members
                               );
                ASSERT(NT_SUCCESS(NtStatus));

                NtStatus = STATUS_MEMBER_NOT_IN_ALIAS;
                for ( i=0; i<MemberCount; i++) {
                    if (Members[i] == AliasRid) {
                        NtStatus = STATUS_SUCCESS;
                        break;
                    }
                }

                if (NT_SUCCESS(NtStatus)) {
                    printf("Succeeded\n");
                } else {
                    printf("Failed\n");
                    printf("Service returned SUCCESS, but alias not in account alias membership list.\n");
                    printf("Alias Membership :\n");
                    for (i=0; i<MemberCount; i++) {
                        printf("0x%lx\n", Members[i]);
                    }
                    DebugBreak();
                    TestStatus = FALSE;
                }

                if (Members != NULL) {
                    SamFreeMemory( Members );
                }
            }

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }

        DeleteUserSid(UserSid1);




        printf("      Add alias as member . . . . . . . . . . . . . . . . .     ");

        //
        // Specify an alias in the current domain be added to this alias
        //


        UserSid1 = CreateUserSid(DomainSid, AliasRid2);
        ASSERT(UserSid1 != NULL);


        NtStatus = SamAddMemberToAlias(
                       AliasHandle1,
                       UserSid1
                       );

        if (NtStatus != STATUS_INVALID_MEMBER) {

                printf("Failed\n");
                printf("Expected service to return STATUS_INVALID_MEMBER, actually returned 0x%lx.\n", NtStatus);
                DebugBreak();
                TestStatus = FALSE;
        } else {
                printf("Succeeded\n");
        }

        DeleteUserSid(UserSid1);



        printf("      Add non-existant account in this domain as member . .     ");

        //
        // Specify a non-existant account in the current domain be added to this alias
        //


        UserSid1 = CreateUserSid(DomainSid, 32567); // Random rid
        ASSERT(UserSid1 != NULL);


        NtStatus = SamAddMemberToAlias(
                       AliasHandle1,
                       UserSid1
                       );

        if (NtStatus != STATUS_NO_SUCH_MEMBER) {

                printf("Failed\n");
                printf("Expected service to return STATUS_NO_SUCH_MEMBER, actually returned 0x%lx.\n", NtStatus);
                DebugBreak();
                TestStatus = FALSE;
        } else {
                printf("Succeeded\n");
        }

        DeleteUserSid(UserSid1);



        printf("      Remove Non-member . . . . . . . . . . . . . . . . . .      ");

        //
        // Specify a non-existant user be removed from this alias
        //

        {
            PSID    ForeignDomainSid;

            ForeignDomainSid = CreateUserSid(DomainSid, 35775); // random domain sub-authority
            ASSERT(ForeignDomainSid != NULL);

            UserRid = 623545;    // Random user rid

            UserSid1 = CreateUserSid(ForeignDomainSid, UserRid);
            ASSERT(UserSid1 != NULL);

            DeleteUserSid(ForeignDomainSid);
        }

        NtStatus = SamRemoveMemberFromAlias( AliasHandle1, UserSid1 );

        if (NtStatus == STATUS_MEMBER_NOT_IN_ALIAS) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }

        DeleteUserSid(UserSid1);

        NtStatus = SamDeleteAlias( AliasHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));




    }

    return(TestStatus);

}


///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// User Object Test Suite                                                    //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////


BOOLEAN
UserTestSuite(
    HANDLE DomainHandle,
    ULONG Pass
    )


{

    PUSER_ALL_INFORMATION All, All2;
    NTSTATUS            NtStatus, IgnoreStatus, TmpStatus;
    HANDLE              UserHandle1, UserHandle2, GroupHandle1;
    ULONG               CountReturned, NameLength, MembershipCount, i;
    ULONG               UserRid, GroupRid;
    PVOID               Buffer, Buffer1, Buffer2;
    SAM_ENUMERATE_HANDLE EnumerationContext;
    USER_GENERAL_INFORMATION GeneralInformation;
    USER_LOGON_INFORMATION LogonInformation;
    USER_ACCOUNT_INFORMATION AccountInformation;
    PSID_NAME_USE       LookedUpUses;
    PULONG              LookedUpRids;
    UNICODE_STRING      AccountNames[10], AccountName;
    STRING              AccountNameAnsi, TmpAnsiString;




    BOOLEAN             IndividualTestSucceeded, DeleteUser;
    BOOLEAN             TestStatus = TRUE;




    if (Pass == 1) {
        // This test suite assumes that lookup and enumeration API funciton
        // properly.
        //

        printf("\n");
        printf("\n");
        printf("  User  (Pass #1) . . . . . . . . . . . . . . . . . . .   Test\n");

        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Open User  Suite                                                      //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("    Open User   . . . . . . . . . . . . . . . . . . . . .   Suite\n");
        printf("      Open Users  . . . . . . . . . . . . . . . . . . . . .     ");
        IndividualTestSucceeded = TRUE;
        EnumerationContext = 0;
        NtStatus = SamEnumerateUsersInDomain(
                       DomainHandle,
                       &EnumerationContext,
                       0,
                       &Buffer,
                       12000,                   // PreferedMaximumLength
                       &CountReturned
                       );

        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(Buffer != NULL);
        ASSERT(CountReturned > 0);

        for (i=0; i<CountReturned; i++) {

            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_ALL_ACCESS,
                           ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId,
                           &UserHandle1
                           );

            if (NT_SUCCESS(NtStatus)) {

                NtStatus = SamOpenUser(
                               DomainHandle,
                               GENERIC_READ,
                               ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId,
                               &UserHandle2
                               );

                if (NT_SUCCESS(NtStatus)) {
                    IgnoreStatus = SamCloseHandle( UserHandle2 );
                    ASSERT( NT_SUCCESS(IgnoreStatus) );
                } else {
                    printf("Failed\n");
                    printf("        Completion status is 0x%lx\n", NtStatus);
                    printf("        Failed opening User  second time.\n");
                    printf("        Rid of account is:   0x%lx\n",
                        ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId);
                    printf("        Name of account is:  %wZ\n",
                        &((PSAM_RID_ENUMERATION)(Buffer))[i].Name );
                    TestStatus = FALSE;
                    IndividualTestSucceeded = FALSE;
                }

                IgnoreStatus = SamCloseHandle( UserHandle1 );
                ASSERT( NT_SUCCESS(IgnoreStatus) );

            } else {

                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                printf("        Failed opening User  for first time.\n");
                printf("        Rid of account is:   0x%lx\n",
                    ((PSAM_RID_ENUMERATION)(Buffer))[i].RelativeId);
                printf("        Name of account is:  %wZ\n",
                    &((PSAM_RID_ENUMERATION)(Buffer))[i].Name );
                TestStatus = FALSE;
                IndividualTestSucceeded = FALSE;
            }

        }


        SamFreeMemory( Buffer );
        if (IndividualTestSucceeded) {
            printf("Succeeded\n");
        }



        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Query User Suite                                                      //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Query User  . . . . . . . . . . . . . . . . . . . . .   Suite\n");

        printf("      Query User  General Information . . . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_GENERAL,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserGeneralInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_GENERAL_INFORMATION *)Buffer)->UserName.MaximumLength
                    >= 0) &&
                     (((USER_GENERAL_INFORMATION *)Buffer)->UserName.Buffer != NULL)
                         ) {

                    printf("Succeeded\n");

                    printf("      Primary Group is:   0x%lx\n",
                     (((USER_GENERAL_INFORMATION *)Buffer)->PrimaryGroupId) );
                    printf("        User  Name is:    *%wZ*\n",
                     &(((USER_GENERAL_INFORMATION *)Buffer)->UserName) );
                    printf("        Full  Name is:    *%wZ*\n",
                     &(((USER_GENERAL_INFORMATION *)Buffer)->FullName) );
                    printf("     Admin Comment is:    *%wZ*\n",
                     &(((USER_GENERAL_INFORMATION *)Buffer)->AdminComment) );
                    printf("      User Comment is:    *%wZ*\n",
                     &(((USER_GENERAL_INFORMATION *)Buffer)->UserComment) );


                } else {
                    printf("Failed\n");
                    printf("        One of the UNICODE_STRINGs  not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query User Name Information . . . . . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_GENERAL,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserNameInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_NAME_INFORMATION *)Buffer)->UserName.MaximumLength > 0) &&
                     (((USER_NAME_INFORMATION *)Buffer)->UserName.Buffer != NULL)
                         ) {

                    printf("Succeeded\n");

                    printf("        User  Name is:    *%wZ*\n",
                     &(((USER_NAME_INFORMATION *)Buffer)->UserName) );
                    printf("        Full  Name is:    *%wZ*\n",
                     &(((USER_NAME_INFORMATION *)Buffer)->FullName) );



                } else {
                    printf("Failed\n");
                    printf("        One of the UNICODE_STRINGs not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query User Account Name Information . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_GENERAL,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserAccountNameInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_ACCOUNT_NAME_INFORMATION *)Buffer)->UserName.MaximumLength > 0) &&
                     (((USER_ACCOUNT_NAME_INFORMATION *)Buffer)->UserName.Buffer != NULL)
                         ) {

                    printf("Succeeded\n");

                    printf("        User  Name is:    *%wZ*\n",
                     &(((USER_ACCOUNT_NAME_INFORMATION *)Buffer)->UserName) );



                } else {
                    printf("Failed\n");
                    printf("        UNICODE_STRING not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query User Full Name Information  . . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_GENERAL,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserFullNameInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_FULL_NAME_INFORMATION *)Buffer)->FullName.MaximumLength
                    >= 0)
                         ) {

                    printf("Succeeded\n");

                    printf("        Full Name is:    *%wZ*\n",
                     &(((USER_FULL_NAME_INFORMATION *)Buffer)->FullName) );



                } else {
                    printf("Failed\n");
                    printf("        UNICODE_STRING not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query User  Admin Comment Information . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_GENERAL,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserAdminCommentInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_ADMIN_COMMENT_INFORMATION *)Buffer)->AdminComment.MaximumLength
                    >= 0)
                         ) {

                    printf("Succeeded\n");

                    printf("     Admin Comment is:    *%wZ*\n",
                     &(((USER_ADMIN_COMMENT_INFORMATION *)Buffer)->AdminComment) );

                } else {
                    printf("Failed\n");
                    printf("        User  Admin Comment not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query User  Primary Group Information . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_GENERAL,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserPrimaryGroupInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {


                printf("Succeeded\n");

                printf("     Primary Group  is:   0x%lx\n",
                 (((USER_PRIMARY_GROUP_INFORMATION *)Buffer)->PrimaryGroupId) );

                SamFreeMemory( Buffer );

            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query User Control Information  . . . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_ACCOUNT,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserControlInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {


                printf("Succeeded\n");

                printf(" Account Control is:      0x%lx\n",
                 (((USER_CONTROL_INFORMATION *)Buffer)->UserAccountControl) );

                SamFreeMemory( Buffer );


            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query User Expiration Information . . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_ACCOUNT,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserExpiresInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {


                printf("Succeeded\n");

                printf(" Account Expires on:      (0x%lx, 0x%lx)\n",
                 (((USER_EXPIRES_INFORMATION *)Buffer)->AccountExpires.HighPart),
                 (((USER_EXPIRES_INFORMATION *)Buffer)->AccountExpires.LowPart) );

                SamFreeMemory( Buffer );


            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );


        printf("      Query User Preferences Information  . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_PREFERENCES | USER_READ_GENERAL,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserPreferencesInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_PREFERENCES_INFORMATION *)Buffer)->UserComment.MaximumLength
                    >= 0)
                         ) {

                    printf("Succeeded\n");

                    printf("     User Comment  is:    *%wZ*\n",
                     &(((USER_PREFERENCES_INFORMATION *)Buffer)->UserComment) );

                } else {
                    printf("Failed\n");
                    printf("        One of the UNICODE_STRINGs not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );





        printf("      Query User Home Directory Information . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_LOGON,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserHomeInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_HOME_INFORMATION *)Buffer)->HomeDirectory.MaximumLength
                    >= 0) &&
                     (((USER_HOME_INFORMATION *)Buffer)->HomeDirectoryDrive.MaximumLength
                     >= 0)
                         ) {

                    printf("Succeeded\n");

                    printf("    Home Directory is:    *%wZ*\n",
                     &(((USER_HOME_INFORMATION *)Buffer)->HomeDirectory) );
                    printf("    Home Directory Drive is:    *%wZ*\n",
                     &(((USER_HOME_INFORMATION *)Buffer)->HomeDirectoryDrive) );


                } else {
                    printf("Failed\n");
                    printf("        String not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query User Script Path Information  . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_LOGON,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserScriptInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_SCRIPT_INFORMATION *)Buffer)->ScriptPath.MaximumLength
                    >= 0)
                         ) {

                    printf("Succeeded\n");

                    printf("      Script Path  is:    *%wZ*\n",
                     &(((USER_SCRIPT_INFORMATION *)Buffer)->ScriptPath) );


                } else {
                    printf("Failed\n");
                    printf("        String not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );



        printf("      Query User ProfilePath Information  . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_LOGON,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserProfileInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_PROFILE_INFORMATION *)Buffer)->ProfilePath.MaximumLength
                    >= 0)
                         ) {

                    printf("Succeeded\n");

                    printf("      Profile Path  is:    *%wZ*\n",
                     &(((USER_PROFILE_INFORMATION *)Buffer)->ProfilePath) );


                } else {
                    printf("Failed\n");
                    printf("        String not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );



        printf("      Query User Logon Information  . . . . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_ACCOUNT | USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserLogonInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_LOGON_INFORMATION *)Buffer)->UserName.MaximumLength > 0)       &&
                     (((USER_LOGON_INFORMATION *)Buffer)->UserName.Buffer != NULL)
                         ) {

                    printf("Succeeded\n");

                    printf("          User RID is:    0x%lx\n",
                     (((USER_LOGON_INFORMATION *)Buffer)->UserId) );
                    printf("     Primary Group is:    0x%lx\n",
                     (((USER_LOGON_INFORMATION *)Buffer)->PrimaryGroupId) );
                    printf("      Logon Units are:    0x%lx\n",
                     (((USER_LOGON_INFORMATION *)Buffer)->LogonHours.UnitsPerWeek) );
                    printf("     Bad PWD count is:    0x%lx\n",
                     (((USER_LOGON_INFORMATION *)Buffer)->BadPasswordCount) );
                    printf("       Logon count is:    0x%lx\n",
                     (((USER_LOGON_INFORMATION *)Buffer)->LogonCount) );

                    printf("        last Logon is:    (0x%lx, 0x%lx)\n",
                     (((USER_LOGON_INFORMATION *)Buffer)->LastLogon.HighPart),
                     (((USER_LOGON_INFORMATION *)Buffer)->LastLogon.LowPart)  );
                    printf("       last Logoff is:    (0x%lx, 0x%lx)\n",
                     (((USER_LOGON_INFORMATION *)Buffer)->LastLogoff.HighPart),
                     (((USER_LOGON_INFORMATION *)Buffer)->LastLogoff.LowPart)  );


                    printf("        User  Name is:    *%wZ*\n",
                     &(((USER_LOGON_INFORMATION *)Buffer)->UserName) );
                    printf("        Full  Name is:    *%wZ*\n",
                     &(((USER_LOGON_INFORMATION *)Buffer)->FullName) );
                    printf("          Home Dir is:    *%wZ*\n",
                     &(((USER_LOGON_INFORMATION *)Buffer)->HomeDirectory) );
                    printf("    Home Dir Drive is:    *%wZ*\n",
                     &(((USER_LOGON_INFORMATION *)Buffer)->HomeDirectoryDrive) );
                    printf("      Script Path  is:    *%wZ*\n",
                     &(((USER_LOGON_INFORMATION *)Buffer)->ScriptPath) );
                    printf("      Profile Path is:    *%wZ*\n",
                     &(((USER_LOGON_INFORMATION *)Buffer)->ProfilePath) );
                    printf("     WorkStations are:    *%wZ*\n",
                     &(((USER_LOGON_INFORMATION *)Buffer)->WorkStations) );




                } else {
                    printf("Failed\n");
                    printf("        One of the UNICODE_STRINGs  not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query User Logon Hours  . . . . . . . . . . . . . . .     ");


        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_LOGON,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserLogonHoursInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                printf("Succeeded\n");

                printf("      Logon Units are:    0x%lx\n",
                 (((USER_LOGON_HOURS_INFORMATION *)Buffer)->LogonHours.UnitsPerWeek) );


                SamFreeMemory( Buffer );

            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        printf("      Query Account Information . . . . . . . . . . . . . .     ");

        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_GENERAL | USER_READ_PREFERENCES |
                       USER_READ_LOGON   | USER_READ_ACCOUNT,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserAccountInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_ACCOUNT_INFORMATION *)Buffer)->UserName.MaximumLength > 0)       &&
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->UserName.Buffer != NULL)
                         ) {

                    printf("Succeeded\n");

                    printf("          User RID is:    0x%lx\n",
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->UserId) );
                    printf("     Primary Group is:    0x%lx\n",
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->PrimaryGroupId) );
                    printf("      Logon Units are:    0x%lx\n",
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->LogonHours.UnitsPerWeek) );
                    printf("     Bad PWD count is:    0x%lx\n",
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->BadPasswordCount) );
                    printf("       Logon count is:    0x%lx\n",
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->LogonCount) );
                    printf("      Account Ctrl is:    0x%lx\n",
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->UserAccountControl) );

                    printf("        last Logon is:    (0x%lx, 0x%lx)\n",
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->LastLogon.HighPart),
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->LastLogon.LowPart)  );
                    printf("       last Logoff is:    (0x%lx, 0x%lx)\n",
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->LastLogoff.HighPart),
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->LastLogoff.LowPart)  );
                    printf("      Pwd Last Set is:    (0x%lx, 0x%lx)\n",
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->PasswordLastSet.HighPart),
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->PasswordLastSet.LowPart)  );
                    printf("   Account Expires is:    (0x%lx, 0x%lx)\n",
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->AccountExpires.HighPart),
                     (((USER_ACCOUNT_INFORMATION *)Buffer)->AccountExpires.LowPart)  );


                    printf("        User  Name is:    *%wZ*\n",
                     &(((USER_ACCOUNT_INFORMATION *)Buffer)->UserName) );
                    printf("        Full  Name is:    *%wZ*\n",
                     &(((USER_ACCOUNT_INFORMATION *)Buffer)->FullName) );
                    printf("          Home Dir is:    *%wZ*\n",
                     &(((USER_ACCOUNT_INFORMATION *)Buffer)->HomeDirectory) );
                    printf("    Home Dir Drive is:    *%wZ*\n",
                     &(((USER_ACCOUNT_INFORMATION *)Buffer)->HomeDirectoryDrive) );
                    printf("      Script Path  is:    *%wZ*\n",
                     &(((USER_ACCOUNT_INFORMATION *)Buffer)->ScriptPath) );
                    printf("     Profile Path  is:    *%wZ*\n",
                     &(((USER_ACCOUNT_INFORMATION *)Buffer)->ProfilePath) );
                    printf("     Admin Comment is:    *%wZ*\n",
                     &(((USER_ACCOUNT_INFORMATION *)Buffer)->AdminComment) );
                    printf("     WorkStations are:    *%wZ*\n",
                     &(((USER_ACCOUNT_INFORMATION *)Buffer)->WorkStations) );



                } else {
                    printf("Failed\n");
                    printf("        One of the UNICODE_STRINGs  not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );








        printf("      Query Workstations Information  . . . . . . . . . . .     ");

        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_LOGON,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserWorkStationsInformation,
                       &Buffer
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                if ( (((USER_WORKSTATIONS_INFORMATION *)Buffer)->WorkStations.MaximumLength
                    >= 0)
                         ) {

                    printf("Succeeded\n");

                    printf("      Workstations is:    *%wZ*\n",
                     &(((USER_WORKSTATIONS_INFORMATION *)Buffer)->WorkStations) );


                } else {
                    printf("Failed\n");
                    printf("        String not returned.\n");
                    TestStatus = FALSE;
                }
                SamFreeMemory( Buffer );
            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );





        printf("      Query Internal1 Information  . . . . . . . . . . .     ");

        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_LOGON,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserInternal1Information,
                       &Buffer
                       );

        if ( NtStatus == STATUS_INVALID_INFO_CLASS ) {

            //
            // We're not a trusted client, so we expected this to fail.
            //

            printf("Succeeded\n");

        } else {

            printf("Failed\n");
            printf("        Status was %lx.\n", NtStatus );
            TestStatus = FALSE;
            if ( NT_SUCCESS( NtStatus ) ) {

                SamFreeMemory( Buffer );
            }
        }

// This is the code that USED to test this function, when it was allowed
// for non-trusted clients.
//
//        if (NT_SUCCESS(NtStatus)) {
//            if (Buffer != NULL) {
//
//                if ( (((USER_INTERNAL1_INFORMATION *)Buffer)->CaseInsensitiveDbcs.MaximumLength > 0) &&
//                     (((USER_INTERNAL1_INFORMATION *)Buffer)->CaseInsensitiveDbcs.Buffer != NULL) &&
//                     (((USER_INTERNAL1_INFORMATION *)Buffer)->CaseSensitiveUnicode.MaximumLength > 0) &&
//                     (((USER_INTERNAL1_INFORMATION *)Buffer)->CaseSensitiveUnicode.Buffer != NULL)
//                         ) {
//
//                     printf("Succeeded\n");
//
//                     //
//                     // Print them out as strings, even though they've been
//                     // through a OWF.
//                     //
//
//                     printf("      CaseInsensitiveDbcs is:    *%s*\n",
//                      &(((USER_INTERNAL1_INFORMATION *)Buffer)->CaseInsensitiveDbcs) );
//
//                     printf("      CaseSensitiveUnicode is:    *%s*\n",
//                      &(((USER_INTERNAL1_INFORMATION *)Buffer)->CaseSensitiveUnicode) );
//
//
//                } else {
//                    printf("Failed\n");
//                    printf("        One of the strings not returned.\n");
//                    TestStatus = FALSE;
//                }
//                SamFreeMemory( Buffer );
//            } else {
//                printf("Failed\n");
//                printf("        Buffer address not set on return.\n");
//                printf("        RPC should have allocated a buffer.\n");
//                TestStatus = FALSE;
//            }
//        } else {
//            printf("Failed\n");
//            printf("        Completion status is 0x%lx\n", NtStatus);
//            TestStatus = FALSE;
//        }

        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );





        printf("      Query Internal2 Information  . . . . . . . . . . .     ");

        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_LOGON,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserInternal2Information,
                       &Buffer
                       );

        if ( NtStatus == STATUS_INVALID_INFO_CLASS ) {

            //
            // We're not a trusted client, so we don't expect to be able
            // to do this.
            //

            printf("Succeeded.\n");

        } else {

            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
            SamFreeMemory( Buffer );
        }

// This is the code that USED to test this function, when non-trusted
// clients were allowed to do this...
//
//        if (NT_SUCCESS(NtStatus)) {
//            if (Buffer != NULL) {
//
//                printf("Succeeded\n");
//
//                printf("        last Logon is:    (0x%lx, 0x%lx)\n",
//                 (((USER_INTERNAL2_INFORMATION *)Buffer)->LastLogon.HighPart),
//                 (((USER_INTERNAL2_INFORMATION *)Buffer)->LastLogon.LowPart)  );
//                printf("       last Logoff is:    (0x%lx, 0x%lx)\n",
//                 (((USER_INTERNAL2_INFORMATION *)Buffer)->LastLogoff.HighPart),
//                 (((USER_INTERNAL2_INFORMATION *)Buffer)->LastLogoff.LowPart)  );
//                printf("       BadPwdCount is:    (0x%x)\n",
//                 ((USER_INTERNAL2_INFORMATION *)Buffer)->BadPasswordCount );
//                printf("       LogonCount  is:    (0x%x)\n",
//                 ((USER_INTERNAL2_INFORMATION *)Buffer)->LogonCount );
//
//                SamFreeMemory( Buffer );
//            } else {
//                printf("Failed\n");
//                printf("        Buffer address not set on return.\n");
//                printf("        RPC should have allocated a buffer.\n");
//                TestStatus = FALSE;
//            }
//        } else {
//            printf("Failed\n");
//            printf("        Completion status is 0x%lx\n", NtStatus);
//            TestStatus = FALSE;
//        }

        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );





        printf("      Query Set Password Information  . . . . . . . . . . .     ");




        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_READ_LOGON,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserSetPasswordInformation,
                       &Buffer
                       );
        if (NtStatus == STATUS_INVALID_INFO_CLASS ) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            printf("        Expected 0x%lx (INVALID_INFO_CLASS)\n", STATUS_INVALID_INFO_CLASS);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );




        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Get Groups For User Suite                                             //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Get Groups For User . . . . . . . . . . . . . . . . .   Suite\n");

        printf("      Get Groups For Well-Known Account . . . . . . . . . .     ");

        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_LIST_GROUPS,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;
        NtStatus = SamGetGroupsForUser(
                       UserHandle1,
                       (PGROUP_MEMBERSHIP *)&Buffer,
                       &MembershipCount
                       );
        if (NT_SUCCESS(NtStatus)) {
            if (Buffer != NULL) {

                printf("Succeeded\n");


                printf("          Member of:    %d groups\n", MembershipCount);
                for ( i=0; i<MembershipCount; i++) {

                    printf("      Group[%d] Rid/Attributes:      0x%lx/0x%lx\n",
                        i,
                        (((PGROUP_MEMBERSHIP)Buffer)[i].RelativeId),
                        (((PGROUP_MEMBERSHIP)Buffer)[i].Attributes)
                        );

                }

                SamFreeMemory( Buffer );


            } else {
                printf("Failed\n");
                printf("        Buffer address not set on return.\n");
                printf("        RPC should have allocated a buffer.\n");
                TestStatus = FALSE;
            }
        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );



        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Set User Suite                                                        //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Set User  . . . . . . . . . . . . . . . . . . . . . .   Suite\n");

        printf("      Set General Information . . . . . . . . . . . . . . .     ");
        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_ALL_ACCESS,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        //
        // Make the parameter marshallable, but don't worry about values.
        //

        GeneralInformation.UserName = DummyName1;
        GeneralInformation.FullName = DummyName1;
        GeneralInformation.AdminComment = DummyName1;
        GeneralInformation.UserComment  = DummyName1;

        Buffer = &GeneralInformation;
        NtStatus = SamSetInformationUser(
                       UserHandle1,
                       UserGeneralInformation,
                       Buffer
                       );
        if (NtStatus == STATUS_INVALID_INFO_CLASS ) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            printf("        Expected 0x%lx (INVALID_INFO_CLASS)\n", STATUS_INVALID_INFO_CLASS);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );



        printf("      Set Preferences Information . . . . . . . . . . . . .     ");
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_READ_GENERAL | USER_WRITE_PREFERENCES | USER_READ_PREFERENCES,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // Get the current value...
            //

            Buffer1 = NULL;
            NtStatus = SamQueryInformationUser(
                           UserHandle1,
                           UserPreferencesInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);


            //
            // Change the fields to  new values and write them out.
            //

            NameLength = ((USER_PREFERENCES_INFORMATION *)Buffer1)->UserComment.Length;
            if (  NameLength == DummyString1.Length ) {
                ((USER_PREFERENCES_INFORMATION *)Buffer1)->UserComment = DummyString2;
            } else {
                ((USER_PREFERENCES_INFORMATION *)Buffer1)->UserComment = DummyString1;
            }

            ((USER_PREFERENCES_INFORMATION *)Buffer1)->CountryCode += 1;
            ((USER_PREFERENCES_INFORMATION *)Buffer1)->CodePage += 1;

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserPreferencesInformation,
                           Buffer1
                           );
            if ( NT_SUCCESS(NtStatus) ) {

                //
                // Now check that the change was really made...
                //

                NtStatus = SamQueryInformationUser(
                               UserHandle1,
                               UserPreferencesInformation,
                               &Buffer2
                               );
                ASSERT(NT_SUCCESS( NtStatus ) );
                if (
                    !RtlCompareString(
                        (PSTRING)&((USER_PREFERENCES_INFORMATION *)Buffer1)->UserComment,
                        (PSTRING)&((USER_PREFERENCES_INFORMATION *)Buffer2)->UserComment,
                        TRUE)
                        &&
                        (((USER_PREFERENCES_INFORMATION *)Buffer1)->CountryCode ==
                         ((USER_PREFERENCES_INFORMATION *)Buffer2)->CountryCode)
                        &&
                        (((USER_PREFERENCES_INFORMATION *)Buffer1)->CodePage ==
                         ((USER_PREFERENCES_INFORMATION *)Buffer2)->CodePage)
                    ) {

                    printf("Succeeded\n");

                    //
                    // Change back some fields to keep from screwing up our database
                    //

                    ((USER_PREFERENCES_INFORMATION *)Buffer1)->CountryCode -= 1;
                    ((USER_PREFERENCES_INFORMATION *)Buffer1)->CodePage    -= 1;

                    IgnoreStatus = SamSetInformationUser(
                                       UserHandle1,
                                       UserPreferencesInformation,
                                       Buffer1
                                       );
                    ASSERT(NT_SUCCESS(IgnoreStatus));

                } else {

                    printf("Failed\n");
                    printf("        Values queried don't match values written\n");
                    printf("        UserComment Written is   %wZ\n",
                        (PUNICODE_STRING)&((USER_PREFERENCES_INFORMATION *)Buffer1)->UserComment);
                    printf("        UserComment Retrieved is %wZ\n",
                        (PUNICODE_STRING)&((USER_PREFERENCES_INFORMATION *)Buffer2)->UserComment);
                    printf("        CountryCode Written is   0x%lx\n",
                        (ULONG)((USER_PREFERENCES_INFORMATION *)Buffer1)->CountryCode);
                    printf("        CountryCode Retrieved is 0x%lx\n",
                        (ULONG)((USER_PREFERENCES_INFORMATION *)Buffer2)->CountryCode);
                    printf("        CodePage Written is   0x%lx\n",
                        (ULONG)((USER_PREFERENCES_INFORMATION *)Buffer1)->CodePage);
                    printf("        CodePage Retrieved is 0x%lx\n",
                        (ULONG)((USER_PREFERENCES_INFORMATION *)Buffer2)->CodePage);

                    TestStatus = FALSE;

                }

                SamFreeMemory( Buffer1 );
                SamFreeMemory( Buffer2 );

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                SamFreeMemory( Buffer1 );

            }




        printf("      Set Logon Information . . . . . . . . . . . . . . . .     ");
        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_ALL_ACCESS,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        //
        // Make the parameter marshallable, but don't worry about values.
        //

        LogonInformation.UserName       = DummyName1;
        LogonInformation.FullName       = DummyName1;
        LogonInformation.HomeDirectory  = DummyName1;
        LogonInformation.HomeDirectoryDrive = DummyName1;
        LogonInformation.ScriptPath     = DummyName1;
        LogonInformation.ProfilePath    = DummyName1;
        LogonInformation.WorkStations   = DummyName1;

        LogonInformation.LogonHours     = DummyLogonHours;

        Buffer = &LogonInformation;
        NtStatus = SamSetInformationUser(
                       UserHandle1,
                       UserLogonInformation,
                       Buffer
                       );
        if (NtStatus == STATUS_INVALID_INFO_CLASS ) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            printf("        Expected 0x%lx (INVALID_INFO_CLASS)\n", STATUS_INVALID_INFO_CLASS);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );



        printf("      Set Logon Hours Information . . . . . . . . . . . . .     ");
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_WRITE_ACCOUNT | USER_READ_LOGON,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // Get the current value...
            //

            Buffer1 = NULL;
            NtStatus = SamQueryInformationUser(
                           UserHandle1,
                           UserLogonHoursInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);
            ASSERT( ((USER_LOGON_HOURS_INFORMATION *)Buffer1)->LogonHours.LogonHours
                    != NULL);  //Don't support zero length bit masks in this test yet.


            //
            // Change the field to a new value and write it out.
            // We have two choices for out test:
            //                                      NoLogonRestriction
            //                                      DummyLogonHours
            //
            // They are guaranteed to have different values in the
            // LOGON_HOURS_DIFFERENT_OFFSET byte of their respective bit masks.
            //

            if ( 0 == ((USER_LOGON_HOURS_INFORMATION *)Buffer1)->LogonHours.LogonHours[LOGON_HOURS_DIFFERENT_OFFSET]) {
                ((USER_LOGON_HOURS_INFORMATION *)Buffer1)->LogonHours = DummyLogonHours;
            } else {
                ((USER_LOGON_HOURS_INFORMATION *)Buffer1)->LogonHours = NoLogonRestriction;
            }

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserLogonHoursInformation,
                           Buffer1
                           );
            if ( NT_SUCCESS(NtStatus) ) {

                //
                // Now check that the change was really made...
                //

                NtStatus = SamQueryInformationUser(
                               UserHandle1,
                               UserLogonHoursInformation,
                               &Buffer2
                               );
                ASSERT(NT_SUCCESS( NtStatus ) );
                if (
                    ((USER_LOGON_HOURS_INFORMATION *)Buffer1)->LogonHours.LogonHours[LOGON_HOURS_DIFFERENT_OFFSET]
                    ==
                    ((USER_LOGON_HOURS_INFORMATION *)Buffer2)->LogonHours.LogonHours[LOGON_HOURS_DIFFERENT_OFFSET]
                    ) {

                    printf("Succeeded\n");

                } else {

                    printf("Failed\n");
                    printf("        Value queried doesn't match value written\n");
                    printf("        Units Written are   0x%lx\n",
                        ((USER_LOGON_HOURS_INFORMATION *)Buffer1)->LogonHours.UnitsPerWeek);
                    printf("        Units Retrieved are 0x%lx\n",
                        ((USER_LOGON_HOURS_INFORMATION *)Buffer2)->LogonHours.UnitsPerWeek);

                    printf("        Byte 0x%lx of the written bit mask is    0x%lx\n",
                        LOGON_HOURS_DIFFERENT_OFFSET,
                        (ULONG)((USER_LOGON_HOURS_INFORMATION *)Buffer1)->LogonHours.LogonHours[LOGON_HOURS_DIFFERENT_OFFSET]
                        );
                    printf("        Byte 0x%lx of the retrieved bit mask is  0x%lx\n",
                        LOGON_HOURS_DIFFERENT_OFFSET,
                        (ULONG)((USER_LOGON_HOURS_INFORMATION *)Buffer2)->LogonHours.LogonHours[LOGON_HOURS_DIFFERENT_OFFSET]
                        );

                    TestStatus = FALSE;

                }

                SamFreeMemory( Buffer1 );
                SamFreeMemory( Buffer2 );

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                SamFreeMemory( Buffer1 );

            }





        printf("      Set Account Information . . . . . . . . . . . . . . .     ");
        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_WRITE_ACCOUNT        |
                           USER_READ_GENERAL     |
                           USER_READ_PREFERENCES |
                           USER_READ_LOGON,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        //
        // Make the parameter marshallable, but don't worry about values.
        //

        AccountInformation.UserName       = DummyName1;
        AccountInformation.FullName       = DummyName1;
        AccountInformation.HomeDirectory  = DummyName1;
        AccountInformation.HomeDirectoryDrive = DummyName1;
        AccountInformation.ScriptPath     = DummyName1;
        AccountInformation.ProfilePath    = DummyName1;
        AccountInformation.AdminComment   = DummyName1;
        AccountInformation.WorkStations   = DummyName1;

        AccountInformation.LogonHours     = DummyLogonHours;

        Buffer = &AccountInformation;
        NtStatus = SamSetInformationUser(
                       UserHandle1,
                       UserAccountInformation,
                       Buffer
                       );
        if (NtStatus == STATUS_INVALID_INFO_CLASS ) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            printf("        Expected 0x%lx (INVALID_INFO_CLASS)\n", STATUS_INVALID_INFO_CLASS);
            TestStatus = FALSE;
        }
        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );


        printf("      Set Home  . . . . . . . . . . . . . . . . . . . . . .     ");
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_WRITE_ACCOUNT | USER_READ_LOGON,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // Get the current value...
            //

            Buffer1 = NULL;
            NtStatus = SamQueryInformationUser(
                           UserHandle1,
                           UserHomeInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);


            //
            // Change the field to a new value and write it out.
            //

            NameLength = ((USER_HOME_INFORMATION *)Buffer1)->HomeDirectory.Length;
            if (  NameLength == DummyString1.Length ) {
                ((USER_HOME_INFORMATION *)Buffer1)->HomeDirectory = DummyString2;
            } else {
                ((USER_HOME_INFORMATION *)Buffer1)->HomeDirectory = DummyString1;
            }

            NameLength = ((USER_HOME_INFORMATION *)Buffer1)->HomeDirectoryDrive.Length;
            if (  NameLength == DummyString1.Length ) {
                ((USER_HOME_INFORMATION *)Buffer1)->HomeDirectoryDrive = DummyString2;
            } else {
                ((USER_HOME_INFORMATION *)Buffer1)->HomeDirectoryDrive = DummyString1;
            }

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserHomeInformation,
                           Buffer1
                           );
            if ( NT_SUCCESS(NtStatus) ) {

                //
                // Now check that the change was really made...
                //

                NtStatus = SamQueryInformationUser(
                               UserHandle1,
                               UserHomeInformation,
                               &Buffer2
                               );
                ASSERT(NT_SUCCESS( NtStatus ) );

                if (!RtlCompareString(
                        (PSTRING)&((USER_HOME_INFORMATION *)Buffer1)->HomeDirectory,
                        (PSTRING)&((USER_HOME_INFORMATION *)Buffer2)->HomeDirectory,
                        TRUE) ) {

                    if (!RtlCompareString(
                            (PSTRING)&((USER_HOME_INFORMATION *)Buffer1)->HomeDirectoryDrive,
                            (PSTRING)&((USER_HOME_INFORMATION *)Buffer2)->HomeDirectoryDrive,
                            TRUE)
                    ) {
                        printf("Succeeded\n");
                    } else {

                        printf("Failed\n");
                        printf("        Drive Value queried doesn't match value written\n");
                        printf("        Value Written is   %wZ\n",
                            (PUNICODE_STRING)&((USER_HOME_INFORMATION *)Buffer1)->HomeDirectoryDrive);
                        printf("        Value Retrieved is %wZ\n",
                            (PUNICODE_STRING)&((USER_HOME_INFORMATION *)Buffer2)->HomeDirectoryDrive);

                        TestStatus = FALSE;
                    }

                } else {

                    printf("Failed\n");
                    printf("        Directory Value queried doesn't match value written\n");
                    printf("        Value Written is   %wZ\n",
                        (PUNICODE_STRING)&((USER_HOME_INFORMATION *)Buffer1)->HomeDirectory);
                    printf("        Value Retrieved is %wZ\n",
                        (PUNICODE_STRING)&((USER_HOME_INFORMATION *)Buffer2)->HomeDirectory);

                    TestStatus = FALSE;

                }

                SamFreeMemory( Buffer1 );
                SamFreeMemory( Buffer2 );

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                SamFreeMemory( Buffer1 );

            }




        printf("      Set Script  . . . . . . . . . . . . . . . . . . . . .     ");
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_WRITE_ACCOUNT | USER_READ_LOGON,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // Get the current value...
            //

            Buffer1 = NULL;
            NtStatus = SamQueryInformationUser(
                           UserHandle1,
                           UserScriptInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);


            //
            // Change the field to a new value and write it out.
            //

            NameLength = ((USER_SCRIPT_INFORMATION *)Buffer1)->ScriptPath.Length;
            if (  NameLength == DummyString1.Length ) {
                ((USER_SCRIPT_INFORMATION *)Buffer1)->ScriptPath = DummyString2;
            } else {
                ((USER_SCRIPT_INFORMATION *)Buffer1)->ScriptPath = DummyString1;
            }

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserScriptInformation,
                           Buffer1
                           );
            if ( NT_SUCCESS(NtStatus) ) {

                //
                // Now check that the change was really made...
                //

                NtStatus = SamQueryInformationUser(
                               UserHandle1,
                               UserScriptInformation,
                               &Buffer2
                               );
                ASSERT(NT_SUCCESS( NtStatus ) );
                if (
                    !RtlCompareString(
                        (PSTRING)&((USER_SCRIPT_INFORMATION *)Buffer1)->ScriptPath,
                        (PSTRING)&((USER_SCRIPT_INFORMATION *)Buffer2)->ScriptPath,
                        TRUE)
                    ) {

                    printf("Succeeded\n");

                } else {

                    printf("Failed\n");
                    printf("        Value queried doesn't match value written\n");
                    printf("        Value Written is   %wZ\n",
                        (PUNICODE_STRING)&((USER_SCRIPT_INFORMATION *)Buffer1)->ScriptPath);
                    printf("        Value Retrieved is %wZ\n",
                        (PUNICODE_STRING)&((USER_SCRIPT_INFORMATION *)Buffer2)->ScriptPath);

                    TestStatus = FALSE;

                }

                SamFreeMemory( Buffer1 );
                SamFreeMemory( Buffer2 );

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                SamFreeMemory( Buffer1 );

            }




        printf("      Set Profile . . . . . . . . . . . . . . . . . . . . .     ");
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_WRITE_ACCOUNT | USER_READ_LOGON,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // Get the current value...
            //

            Buffer1 = NULL;
            NtStatus = SamQueryInformationUser(
                           UserHandle1,
                           UserProfileInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);


            //
            // Change the field to a new value and write it out.
            //

            NameLength = ((USER_PROFILE_INFORMATION *)Buffer1)->ProfilePath.Length;
            if (  NameLength == DummyString1.Length ) {
                ((USER_PROFILE_INFORMATION *)Buffer1)->ProfilePath = DummyString2;
            } else {
                ((USER_PROFILE_INFORMATION *)Buffer1)->ProfilePath = DummyString1;
            }

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserProfileInformation,
                           Buffer1
                           );
            if ( NT_SUCCESS(NtStatus) ) {

                //
                // Now check that the change was really made...
                //

                NtStatus = SamQueryInformationUser(
                               UserHandle1,
                               UserProfileInformation,
                               &Buffer2
                               );
                ASSERT(NT_SUCCESS( NtStatus ) );
                if (
                    !RtlCompareString(
                        (PSTRING)&((USER_PROFILE_INFORMATION *)Buffer1)->ProfilePath,
                        (PSTRING)&((USER_PROFILE_INFORMATION *)Buffer2)->ProfilePath,
                        TRUE)
                    ) {

                    printf("Succeeded\n");

                } else {

                    printf("Failed\n");
                    printf("        Value queried doesn't match value written\n");
                    printf("        Value Written is   %wZ\n",
                        (PUNICODE_STRING)&((USER_PROFILE_INFORMATION *)Buffer1)->ProfilePath);
                    printf("        Value Retrieved is %wZ\n",
                        (PUNICODE_STRING)&((USER_PROFILE_INFORMATION *)Buffer2)->ProfilePath);

                    TestStatus = FALSE;

                }

                SamFreeMemory( Buffer1 );
                SamFreeMemory( Buffer2 );

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                SamFreeMemory( Buffer1 );

            }




        printf("      Set Admin Comment . . . . . . . . . . . . . . . . . .     ");

            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_WRITE_ACCOUNT | USER_READ_GENERAL,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // Get the current value...
            //

            Buffer1 = NULL;
            NtStatus = SamQueryInformationUser(
                           UserHandle1,
                           UserAdminCommentInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);


            //
            // Change the field to a new value and write it out.
            //

            NameLength = ((USER_ADMIN_COMMENT_INFORMATION *)Buffer1)->AdminComment.Length;
            if (  NameLength == DummyString1.Length ) {
                ((USER_ADMIN_COMMENT_INFORMATION *)Buffer1)->AdminComment = DummyString2;
            } else {
                ((USER_ADMIN_COMMENT_INFORMATION *)Buffer1)->AdminComment = DummyString1;
            }

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserAdminCommentInformation,
                           Buffer1
                           );
            if ( NT_SUCCESS(NtStatus) ) {

                //
                // Now check that the change was really made...
                //

                NtStatus = SamQueryInformationUser(
                               UserHandle1,
                               UserAdminCommentInformation,
                               &Buffer2
                               );
                ASSERT(NT_SUCCESS( NtStatus ) );
                if (
                    !RtlCompareString(
                        (PSTRING)&((USER_ADMIN_COMMENT_INFORMATION *)Buffer1)->AdminComment,
                        (PSTRING)&((USER_ADMIN_COMMENT_INFORMATION *)Buffer2)->AdminComment,
                        TRUE)
                    ) {

                    printf("Succeeded\n");

                } else {

                    printf("Failed\n");
                    printf("        Value queried doesn't match value written\n");
                    printf("        Value Written is   %wZ\n",
                        (PUNICODE_STRING)&((USER_ADMIN_COMMENT_INFORMATION *)Buffer1)->AdminComment);
                    printf("        Value Retrieved is %wZ\n",
                        (PUNICODE_STRING)&((USER_ADMIN_COMMENT_INFORMATION *)Buffer2)->AdminComment);

                    TestStatus = FALSE;

                }

                SamFreeMemory( Buffer1 );
                SamFreeMemory( Buffer2 );

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                SamFreeMemory( Buffer1 );

            }


        printf("      Set Workstations  . . . . . . . . . . . . . . . . . .     ");
        printf("BROKEN TEST - NOT TESTED\n");
#ifdef BROKEN
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_WRITE_ACCOUNT | USER_READ_LOGON,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // Get the current value...
            //

            Buffer1 = NULL;
            NtStatus = SamQueryInformationUser(
                           UserHandle1,
                           UserWorkStationsInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);


            //
            // Change the field to a new value and write it out.
            //

            NameLength = ((USER_WORKSTATIONS_INFORMATION *)Buffer1)->WorkStations.Length;
            if (  NameLength == DummyString1.Length ) {
                ((USER_WORKSTATIONS_INFORMATION *)Buffer1)->WorkStations = DummyString2;
            } else {
                ((USER_WORKSTATIONS_INFORMATION *)Buffer1)->WorkStations = DummyString1;
            }

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserWorkStationsInformation,
                           Buffer1
                           );
            if ( NT_SUCCESS(NtStatus) ) {

                //
                // Now check that the change was really made...
                //

                NtStatus = SamQueryInformationUser(
                               UserHandle1,
                               UserWorkStationsInformation,
                               &Buffer2
                               );
                ASSERT(NT_SUCCESS( NtStatus ) );
                if (
                    !RtlCompareString(
                        (PSTRING)&((USER_WORKSTATIONS_INFORMATION *)Buffer1)->WorkStations,
                        (PSTRING)&((USER_WORKSTATIONS_INFORMATION *)Buffer2)->WorkStations,
                        TRUE)
                    ) {

                    printf("Succeeded\n");

                } else {

                    printf("Failed\n");
                    printf("        Value queried doesn't match value written\n");
                    printf("        Value Written is   %wZ\n",
                        (PUNICODE_STRING)&((USER_WORKSTATIONS_INFORMATION *)Buffer1)->WorkStations);
                    printf("        Value Retrieved is %wZ\n",
                        (PUNICODE_STRING)&((USER_WORKSTATIONS_INFORMATION *)Buffer2)->WorkStations);

                    TestStatus = FALSE;

                }

                SamFreeMemory( Buffer1 );
                SamFreeMemory( Buffer2 );

            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
                SamFreeMemory( Buffer1 );

            }
#endif //BROKEN


        printf("      Set Internal1   . . . . . . . . . . . . . . . . . . .     ");

            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_WRITE_ACCOUNT | USER_READ_LOGON | USER_FORCE_PASSWORD_CHANGE,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // We can't get the current values, since this level is only
            // queryable by trusted clients.  So just try setting a couple
            // of values and make sure that we don't get an error.
            //

            Buffer1 = RtlAllocateHeap( RtlProcessHeap(), 0, sizeof(USER_INTERNAL1_INFORMATION) );
            ASSERT( Buffer1 != NULL );

            ((PUSER_INTERNAL1_INFORMATION)Buffer1)->NtPasswordPresent = FALSE;
            ((PUSER_INTERNAL1_INFORMATION)Buffer1)->LmPasswordPresent = FALSE;

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserInternal1Information,
                           Buffer1
                           );

            if (NtStatus != STATUS_PASSWORD_RESTRICTION) {

                printf("Failed\n");
                printf("    Expected Status = 0x%lx\n", STATUS_PASSWORD_RESTRICTION);
                printf("    Received Status = 0x%lx\n", NtStatus );
                TestStatus = FALSE;

            } else {

                //
                // The NULL password worked, so let's try a real password.
                //

                NtStatus = RtlCalculateNtOwfPassword(
                    &DummyName1,
                    &((PUSER_INTERNAL1_INFORMATION)Buffer1)->NtOwfPassword
                    );
                ASSERT(NT_SUCCESS(NtStatus));

                ((PUSER_INTERNAL1_INFORMATION)Buffer1)->NtPasswordPresent = TRUE;

                NtStatus = RtlCalculateLmOwfPassword(
                    DUMMY_STRING1,
                    &((PUSER_INTERNAL1_INFORMATION)Buffer1)->LmOwfPassword
                    );
                ASSERT(NT_SUCCESS(NtStatus));

                ((PUSER_INTERNAL1_INFORMATION)Buffer1)->LmPasswordPresent = TRUE;

                NtStatus = SamSetInformationUser(
                               UserHandle1,
                               UserInternal1Information,
                               Buffer1
                               );

                if ( NT_SUCCESS(NtStatus) ) {

                    printf("Succeeded\n");

                } else {

                    printf("Failed\n");
                    printf("    Return status was %lx\n", NtStatus );
                    TestStatus = FALSE;
                }
            }

            RtlFreeHeap( RtlProcessHeap(), 0, Buffer1 );


// This is the code that used to be here, when UserInternal1Information was
// queryable by non-trusted clients...
//
//            Buffer1 = NULL;
//            NtStatus = SamQueryInformationUser(
//                           UserHandle1,
//                           UserInternal1Information,
//                           &Buffer1
//                           );
//            TST_SUCCESS_ASSERT(NtStatus);
//            ASSERT(Buffer1 != NULL);
//
//            //
//            // The passwords were initially empty.  Put in some random
//            // OWF passwords, and have them written out.
//            //
//
//            NtStatus = RtlCalculateNtOwfPassword(
//                (PNT_PASSWORD)&DummyName1,
//                &EncryptedPasswordBuffer
//                );
//
//            ((USER_INTERNAL1_INFORMATION *)Buffer1)->CaseSensitiveUnicode.Buffer = (PCHAR)&EncryptedPasswordBuffer;
//            ((USER_INTERNAL1_INFORMATION *)Buffer1)->CaseSensitiveUnicode.Length = 16;
//            ((USER_INTERNAL1_INFORMATION *)Buffer1)->CaseSensitiveUnicode.MaximumLength = 16;
//
//            NtStatus = RtlCalculateNtOwfPassword(
//                (PNT_PASSWORD)&DummyName2,
//                &EncryptedPasswordBuffer2
//                );
//
//            ((USER_INTERNAL1_INFORMATION *)Buffer1)->CaseInsensitiveDbcs.Buffer = (PCHAR)&EncryptedPasswordBuffer2;
//            ((USER_INTERNAL1_INFORMATION *)Buffer1)->CaseInsensitiveDbcs.Length = 16;
//            ((USER_INTERNAL1_INFORMATION *)Buffer1)->CaseInsensitiveDbcs.MaximumLength = 16;
//
//            NtStatus = SamSetInformationUser(
//                           UserHandle1,
//                           UserInternal1Information,
//                           Buffer1
//                           );
//            if ( NT_SUCCESS(NtStatus) ) {
//
//                //
//                // Now check that the change was really made...
//                //
//
//                NtStatus = SamQueryInformationUser(
//                               UserHandle1,
//                               UserInternal1Information,
//                               &Buffer2
//                               );
//                ASSERT(NT_SUCCESS( NtStatus ) );
//
//                if ( (
//                    !RtlCompareString(
//                        (PSTRING)&((USER_INTERNAL1_INFORMATION *)Buffer1)->CaseSensitiveUnicode,
//                        (PSTRING)&((USER_INTERNAL1_INFORMATION *)Buffer2)->CaseSensitiveUnicode,
//                        TRUE)
//                    ) || (
//                    !RtlCompareString(
//                        (PSTRING)&((USER_INTERNAL1_INFORMATION *)Buffer1)->CaseInsensitiveDbcs,
//                        (PSTRING)&((USER_INTERNAL1_INFORMATION *)Buffer2)->CaseInsensitiveDbcs,
//                        TRUE)
//                    ) ) {
//
//                    printf("Succeeded\n");
//
//                } else {
//
//                    printf("Failed\n");
//                    printf("        Value queried doesn't match value written\n");
//                    printf("        CaseInsensitiveDbcs Written is   %wZ\n",
//                        (PUNICODE_STRING)&((USER_INTERNAL1_INFORMATION *)Buffer1)->CaseInsensitiveDbcs);
//                    printf("        CaseInsensitiveDbcs Retrieved is %wZ\n",
//                        (PUNICODE_STRING)&((USER_INTERNAL1_INFORMATION *)Buffer2)->CaseInsensitiveDbcs);
//                    printf("        CaseSensitiveUnicode Written is   %wZ\n",
//                        (PUNICODE_STRING)&((USER_INTERNAL1_INFORMATION *)Buffer1)->CaseSensitiveUnicode);
//                    printf("        CaseSensitiveUnicode Retrieved is %wZ\n",
//                        (PUNICODE_STRING)&((USER_INTERNAL1_INFORMATION *)Buffer2)->CaseSensitiveUnicode);
//
//                    TestStatus = FALSE;
//
//                }
//
//                SamFreeMemory( Buffer1 );
//                SamFreeMemory( Buffer2 );
//
//            } else {
//                printf("Failed\n");
//                printf("        Completion status is 0x%lx\n", NtStatus);
//                TestStatus = FALSE;
//                SamFreeMemory( Buffer1 );
//
//            }



        printf("      Set Internal2   . . . . . . . . . . . . . . . . . . .     ");

            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_WRITE_ACCOUNT | USER_READ_LOGON,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // We can't get the current values, since this level is only
            // queryable by trusted clients.  We can't set either, but
            // try it and make sure we get the correct error.
            //

            Buffer1 = RtlAllocateHeap( RtlProcessHeap(), 0, sizeof(USER_INTERNAL2_INFORMATION) );
            ASSERT( Buffer1 != NULL );

            ((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogon.HighPart = 1;
            ((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogoff.HighPart = 2;
            ((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogon.LowPart = 3;
            ((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogoff.LowPart = 4;
            ((USER_INTERNAL2_INFORMATION *)Buffer1)->BadPasswordCount = 5;
            ((USER_INTERNAL2_INFORMATION *)Buffer1)->LogonCount = 6;

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserInternal2Information,
                           Buffer1
                           );

            RtlFreeHeap( RtlProcessHeap(), 0, Buffer1 );

            if ( NtStatus == STATUS_INVALID_INFO_CLASS ) {

                printf("Succeeded\n");

            } else {

                printf("Failed\n");
                printf("    Expected Status = 0x%lx\n", STATUS_INVALID_INFO_CLASS);
                printf("    Received Status = 0x%lx\n", NtStatus );
                TestStatus = FALSE;
            }

// This is the code that was here when UserInternal2Information could be
// queried and set by non-trusted clients...
//
//            //
//            // Get the current values...
//            //
//
//            Buffer1 = NULL;
//            NtStatus = SamQueryInformationUser(
//                           UserHandle1,
//                           UserInternal2Information,
//                           &Buffer1
//                           );
//            TST_SUCCESS_ASSERT(NtStatus);
//            ASSERT(Buffer1 != NULL);
//
//            //
//            // Now change the fields and write them out.
//            //
//
//            ((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogon.HighPart += 1;
//            ((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogoff.HighPart += 1;
//            ((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogon.LowPart += 2;
//            ((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogoff.LowPart += 2;
//            ((USER_INTERNAL2_INFORMATION *)Buffer1)->BadPasswordCount += 1;
//            ((USER_INTERNAL2_INFORMATION *)Buffer1)->LogonCount += 1;
//
//            NtStatus = SamSetInformationUser(
//                           UserHandle1,
//                           UserInternal2Information,
//                           Buffer1
//                           );
//            if ( NT_SUCCESS(NtStatus) ) {
//
//                //
//                // Now check that the change was really made...
//                //
//
//                NtStatus = SamQueryInformationUser(
//                               UserHandle1,
//                               UserInternal2Information,
//                               &Buffer2
//                               );
//                ASSERT(NT_SUCCESS( NtStatus ) );
//                if (
//                    (((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogon.HighPart ==
//                    ((USER_INTERNAL2_INFORMATION *)Buffer2)->LastLogon.HighPart) &&
//                    (((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogon.LowPart ==
//                    ((USER_INTERNAL2_INFORMATION *)Buffer2)->LastLogon.LowPart) &&
//                    (((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogoff.HighPart ==
//                    ((USER_INTERNAL2_INFORMATION *)Buffer2)->LastLogoff.HighPart) &&
//                    (((USER_INTERNAL2_INFORMATION *)Buffer1)->LastLogoff.LowPart ==
//                    ((USER_INTERNAL2_INFORMATION *)Buffer2)->LastLogoff.LowPart) &&
//                    (((USER_INTERNAL2_INFORMATION *)Buffer1)->BadPasswordCount ==
//                    ((USER_INTERNAL2_INFORMATION *)Buffer2)->BadPasswordCount) &&
//                    (((USER_INTERNAL2_INFORMATION *)Buffer1)->LogonCount ==
//                    ((USER_INTERNAL2_INFORMATION *)Buffer2)->LogonCount)
//                     ) {
//
//                    printf("Succeeded\n");
//
//                } else {
//
//                    printf("Failed\n");
//                    printf("        Value queried doesn't match value written\n");
//
//                    TestStatus = FALSE;
//
//                }
//
//                SamFreeMemory( Buffer1 );
//                SamFreeMemory( Buffer2 );
//
//            } else {
//                printf("Failed\n");
//                printf("        Completion status is 0x%lx\n", NtStatus);
//                TestStatus = FALSE;
//                SamFreeMemory( Buffer1 );
//
//            }



        printf("      Set Password  . . . . . . . . . . . . . . . . . . . .     ");

            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_FORCE_PASSWORD_CHANGE,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            //
            // Create a fake cleartext UNICODE password and write it out.
            //

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserSetPasswordInformation,
                           &DummyName2
                           );
            if ( NT_SUCCESS(NtStatus) ) {

                //
                // We can't verify that it really worked, so we just have
                // to trust the return code.
                //

                printf("Succeeded\n");

            } else {

                printf("Failed\n");
                printf("    Return code was %lx\n", NtStatus );
                TestStatus = FALSE;
            }



        printf("      Set Control . . . . . . . . . . . . . . . . . . . . .     ");
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_WRITE_ACCOUNT | USER_READ_ACCOUNT,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            Buffer1 = NULL;
            NtStatus = SamQueryInformationUser(
                           UserHandle1,
                           UserControlInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);

            //
            // Change the value and write it back
            //

            ((USER_CONTROL_INFORMATION *)Buffer1)->UserAccountControl ^= USER_HOME_DIRECTORY_REQUIRED;


            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserControlInformation,
                           Buffer1
                           );
            if (NT_SUCCESS(NtStatus)) {

                //
                // Check the written value to make sure it stuck
                //

                Buffer2 = NULL;
                NtStatus = SamQueryInformationUser(
                               UserHandle1,
                               UserControlInformation,
                               &Buffer2
                               );
                TST_SUCCESS_ASSERT(NtStatus);
                ASSERT(Buffer2 != NULL);

                if ( ((USER_CONTROL_INFORMATION *)Buffer1)->UserAccountControl  ==
                     ((USER_CONTROL_INFORMATION *)Buffer2)->UserAccountControl ) {

                    printf("Succeeded\n");

                    SamFreeMemory( Buffer2 );

                    //
                    // Make sure the account is left enabled to prevent problems.
                    //

                    ((USER_CONTROL_INFORMATION *)Buffer1)->UserAccountControl &= ~USER_ACCOUNT_DISABLED;

                    IgnoreStatus = SamSetInformationUser(
                                       UserHandle1,
                                       UserControlInformation,
                                       Buffer1
                                       );
                    ASSERT(NT_SUCCESS(IgnoreStatus));

                } else {
                    printf("Failed\n");
                    printf("        Returned Value Doesn't Match Set Value.\n");
                    TestStatus = FALSE;
                }
            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
            SamFreeMemory( Buffer1 );
            IgnoreStatus = SamCloseHandle( UserHandle1 );
            ASSERT( NT_SUCCESS(IgnoreStatus) );


        printf("      Set Expires . . . . . . . . . . . . . . . . . . . . .     ");
        printf("BROKEN TEST - NOT TESTED\n");
#ifdef BROKEN
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_WRITE_ACCOUNT | USER_READ_ACCOUNT,
                           DOMAIN_USER_RID_ADMIN,
                           &UserHandle1
                           );
            ASSERT(NT_SUCCESS(NtStatus) );

            Buffer1 = NULL;
            NtStatus = SamQueryInformationUser(
                           UserHandle1,
                           UserExpiresInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);

            //
            // Change the value and write it back
            //

            ((USER_EXPIRES_INFORMATION *)Buffer1)->AccountExpires.LowPart  += 1234;
            ((USER_EXPIRES_INFORMATION *)Buffer1)->AccountExpires.HighPart += 1234;


            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserExpiresInformation,
                           Buffer1
                           );
            if (NT_SUCCESS(NtStatus)) {

                //
                // Check the written value to make sure it stuck
                //

                Buffer2 = NULL;
                NtStatus = SamQueryInformationUser(
                               UserHandle1,
                               UserExpiresInformation,
                               &Buffer2
                               );
                TST_SUCCESS_ASSERT(NtStatus);
                ASSERT(Buffer2 != NULL);

                if ( ( ((USER_EXPIRES_INFORMATION *)Buffer1)->AccountExpires.LowPart  ==
                       ((USER_EXPIRES_INFORMATION *)Buffer2)->AccountExpires.LowPart )  &&
                     ( ((USER_EXPIRES_INFORMATION *)Buffer1)->AccountExpires.HighPart  ==
                       ((USER_EXPIRES_INFORMATION *)Buffer2)->AccountExpires.HighPart ) ) {

                    printf("Succeeded\n");

                    SamFreeMemory( Buffer2 );

                    //
                    // Change the values back
                    //

                    ((USER_EXPIRES_INFORMATION *)Buffer1)->AccountExpires.LowPart  += 1234;
                    ((USER_EXPIRES_INFORMATION *)Buffer1)->AccountExpires.HighPart += 1234;

                    IgnoreStatus = SamSetInformationUser(
                                       UserHandle1,
                                       UserExpiresInformation,
                                       Buffer1
                                       );
                    ASSERT(NT_SUCCESS(IgnoreStatus));

                } else {
                    printf("Failed\n");
                    printf("        Returned Value Doesn't Match Set Value.\n");
                    TestStatus = FALSE;
                }
            } else {
                printf("Failed\n");
                printf("        Completion status is 0x%lx\n", NtStatus);
                TestStatus = FALSE;
            }
            SamFreeMemory( Buffer1 );
            IgnoreStatus = SamCloseHandle( UserHandle1 );
            ASSERT( NT_SUCCESS(IgnoreStatus) );
#endif //BROKEN



        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Change Password For User Suite                                        //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Change Password For User  . . . . . . . . . . . . . .   Suite\n");

        printf("      Change Password For Well-Known User . . . . . . . . .     ");

        NtStatus = SamOpenUser(
                       DomainHandle,
                       USER_CHANGE_PASSWORD,
                       DOMAIN_USER_RID_ADMIN,
                       &UserHandle1
                       );
        ASSERT(NT_SUCCESS(NtStatus) );

        Buffer = NULL;

        //
        // The current password is DummyName2.  Using DummyName2 as the
        // old password, change it to DummyName1 and make sure we get
        // STATUS_SUCCESS.
        //

        NtStatus = SamChangePasswordUser(
                       UserHandle1,
                       &DummyName2,
                       &DummyName1
                       );

        //
        // The current password is DummyName1.  Using something WRONG for
        // the old password, try to change it to DummyName2 and make sure
        // it doesn't succeed.
        //

        if ( NtStatus == STATUS_SUCCESS ) {

            NtStatus = SamChangePasswordUser(
                           UserHandle1,
                           &DummyName2,
                           &DummyName2
                           );

            if ( NtStatus == STATUS_SUCCESS ) {

                NtStatus = STATUS_UNSUCCESSFUL;

            } else {

                NtStatus = STATUS_SUCCESS;
            }
        }

        //
        // The current password is DummyName1.  Using DummyName1 as the
        // old password, change it to DummyName2 and make sure it works
        // since by default there is no password history.
        //

        if ( NtStatus == STATUS_SUCCESS ) {

            NtStatus = SamChangePasswordUser(
                           UserHandle1,
                           &DummyName1,
                           &DummyName2
                           );
        }

        if ( NT_SUCCESS( NtStatus ) ) {

            printf("Succeeded\n");

        } else {

            printf("Failed\n");
            printf("        Status is %lx\n", NtStatus);

            TestStatus = FALSE;
        }

        IgnoreStatus = SamCloseHandle( UserHandle1 );
        ASSERT( NT_SUCCESS(IgnoreStatus) );

    }

// END PASS #1

    if (Pass == 2) {

        printf("\n");
        printf("\n");
        printf("  User  (Pass #2) . . . . . . . . . . . . . . . . . . .   Test\n");


        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Delete User  Suite                                                    //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Delete User   . . . . . . . . . . . . . . . . . . . .   Suite\n");



        printf("      Delete Normal User  . . . . . . . . . . . . . . . . .     ");

        //
        // This User was created in pass #1
        //

        RtlInitString( &AccountNameAnsi, USER_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        NtStatus = SamLookupNamesInDomain(
                       DomainHandle,
                       1,
                       &AccountNames[0],
                       &LookedUpRids,
                       &LookedUpUses
                       );
        TST_SUCCESS_ASSERT(NtStatus);
        ASSERT(LookedUpUses[0] == SidTypeUser);
        RtlFreeUnicodeString( &AccountNames[0] );



        UserHandle1 = NULL;

        NtStatus = SamOpenUser( DomainHandle, DELETE, LookedUpRids[0], &UserHandle1 );
        TST_SUCCESS_ASSERT(NtStatus);
        SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );

        NtStatus = SamDeleteUser( UserHandle1 );
        if (NT_SUCCESS(NtStatus)) {
            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }




        printf("      Delete Admin Group Member . . . . . . . . . . . . . .     ");
        printf("(Unimplemented)\n");

        printf("      Delete Last Admin Group Member  . . . . . . . . . . .     ");
        printf("(Unimplemented)\n");





        ///////////////////////////////////////////////////////////////////////////
        //                                                                       //
        // Set User Suite                                                        //
        //                                                                       //
        ///////////////////////////////////////////////////////////////////////////

        printf("\n");
        printf("    Set User (Pass 2) . . . . . . . . . . . . . . . . . .   Suite\n");

        printf("      Set ALL information. . . . . . . . . . . .     ");
        printf("BROKEN TEST - NOT TESTED\n");
#ifdef BROKEN

        RtlInitString( &AccountNameAnsi, "AllUser" );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        UserRid = 0;
        UserHandle1 = NULL;
        NtStatus = SamCreateUserInDomain(
                       DomainHandle,
                       &AccountName,
                       USER_ALL_ACCESS,
                       &UserHandle1,
                       &UserRid
                       );
        RtlFreeUnicodeString( &AccountName );

        ASSERT(NT_SUCCESS(NtStatus));

        All = NULL;

        NtStatus = SamQueryInformationUser(
                       UserHandle1,
                       UserAllInformation,
                       &All
                       );

        if ( NT_SUCCESS( NtStatus ) ) {

            //
            // Now change some of the data, and set it
            //

            RtlInitString( &TmpAnsiString, "FullName" );
            TmpStatus = RtlAnsiStringToUnicodeString(
                            (PUNICODE_STRING)(&All->FullName),
                            &TmpAnsiString,
                            TRUE );
            ASSERT( NT_SUCCESS( TmpStatus ) );

            RtlInitString( &TmpAnsiString, "HomeDirectory" );
            TmpStatus = RtlAnsiStringToUnicodeString(
                            (PUNICODE_STRING)(&All->HomeDirectory),
                            &TmpAnsiString,
                            TRUE );
            ASSERT( NT_SUCCESS( TmpStatus ) );

            RtlInitString( &TmpAnsiString, "HomeDirectoryDrive" );
            TmpStatus = RtlAnsiStringToUnicodeString(
                            (PUNICODE_STRING)(&All->HomeDirectoryDrive),
                            &TmpAnsiString,
                            TRUE );
            ASSERT( NT_SUCCESS( TmpStatus ) );

            RtlInitString( &TmpAnsiString, "ScriptPath" );
            TmpStatus = RtlAnsiStringToUnicodeString(
                            (PUNICODE_STRING)(&All->ScriptPath),
                            &TmpAnsiString,
                            TRUE );
            ASSERT( NT_SUCCESS( TmpStatus ) );

            RtlInitString( &TmpAnsiString, "ProfilePath" );
            TmpStatus = RtlAnsiStringToUnicodeString(
                            (PUNICODE_STRING)(&All->ProfilePath),
                            &TmpAnsiString,
                            TRUE );
            ASSERT( NT_SUCCESS( TmpStatus ) );

            RtlInitString( &TmpAnsiString, "AdminComment" );
            TmpStatus = RtlAnsiStringToUnicodeString(
                            (PUNICODE_STRING)(&All->AdminComment),
                            &TmpAnsiString,
                            TRUE );
            ASSERT( NT_SUCCESS( TmpStatus ) );

            RtlInitString( &TmpAnsiString, "WorkStations" );
            TmpStatus = RtlAnsiStringToUnicodeString(
                            (PUNICODE_STRING)(&All->WorkStations),
                            &TmpAnsiString,
                            TRUE );
            ASSERT( NT_SUCCESS( TmpStatus ) );

            RtlInitString( &TmpAnsiString, "UserComment" );
            TmpStatus = RtlAnsiStringToUnicodeString(
                            (PUNICODE_STRING)(&All->UserComment),
                            &TmpAnsiString,
                            TRUE );
            ASSERT( NT_SUCCESS( TmpStatus ) );

            RtlInitString( &TmpAnsiString, "Parameters" );
            TmpStatus = RtlAnsiStringToUnicodeString(
                            (PUNICODE_STRING)(&All->Parameters),
                            &TmpAnsiString,
                            TRUE );
            ASSERT( NT_SUCCESS( TmpStatus ) );

            All->CountryCode = 7;
            All->CodePage = 8;

            All->PasswordExpired = TRUE;
            All->NtPasswordPresent = TRUE;
            All->LmPasswordPresent = FALSE;

            RtlInitString( &TmpAnsiString, "NtPassword" );
            TmpStatus = RtlAnsiStringToUnicodeString(
                            (PUNICODE_STRING)(&All->NtPassword),
                            &TmpAnsiString,
                            TRUE );
            ASSERT( NT_SUCCESS( TmpStatus ) );

            All->LogonHours.UnitsPerWeek = 7;

            All->WhichFields =  ( USER_ALL_FULLNAME |
                                USER_ALL_HOMEDIRECTORY |
                                USER_ALL_HOMEDIRECTORYDRIVE |
                                USER_ALL_SCRIPTPATH |
                                USER_ALL_PROFILEPATH |
                                USER_ALL_ADMINCOMMENT |
                                USER_ALL_WORKSTATIONS |
                                USER_ALL_USERCOMMENT |
                                USER_ALL_PARAMETERS |
                                USER_ALL_COUNTRYCODE |
                                USER_ALL_CODEPAGE |
                                USER_ALL_PASSWORDEXPIRED |
                                USER_ALL_NTPASSWORDPRESENT |
                                USER_ALL_LOGONHOURS );

            NtStatus = SamSetInformationUser(
                           UserHandle1,
                           UserAllInformation,
                           All
                           );

            if ( NT_SUCCESS( NtStatus ) ) {

                NtStatus = SamQueryInformationUser(
                               UserHandle1,
                               UserAllInformation,
                               &All2
                               );

                if ( NT_SUCCESS( NtStatus ) ) {

                    //
                    // Verify that queried info is as we set it
                    //

                    if (

                        //
                        // Fields that we didn't touch.  Note that
                        // PasswordMustChange changed anyway, since we
                        // changed from a null to a non-null password.
                        //

                        ( All2->WhichFields != (USER_ALL_READ_GENERAL_MASK    |
                                               USER_ALL_READ_PREFERENCES_MASK |
                                               USER_ALL_READ_ACCOUNT_MASK     |
                                               USER_ALL_READ_LOGON_MASK) ) ||
                        ( !(All->LastLogon.QuadPart ==
                            All2->LastLogon.QuadPart ) ) ||
                        ( !(All->LastLogoff.QuadPart ==
                            All2->LastLogoff.QuadPart ) ) ||
                        ( !(All->PasswordLastSet.QuadPart ==
                            All2->PasswordLastSet.QuadPart ) ) ||
                        ( !(All->AccountExpires.QuadPart ==
                            All2->AccountExpires.QuadPart ) ) ||
                        ( !(All->PasswordCanChange.QuadPart ==
                            All2->PasswordCanChange.QuadPart ) ) ||
                        (  (All->PasswordMustChange.QuadPart ==
                            All2->PasswordMustChange.QuadPart ) ) ||
                        (RtlCompareUnicodeString(
                            &(All->UserName),
                            &(All2->UserName),
                            FALSE) != 0) ||
                        ( All->UserId != All2->UserId ) ||
                        ( All->PrimaryGroupId != All2->PrimaryGroupId ) ||
                        ( All->UserAccountControl != All2->UserAccountControl ) ||
                        ( All->PrivateDataSensitive !=
                            All2->PrivateDataSensitive ) ||

                        // Fields that we changed.  Note that we set
                        // NtPasswordSet, but it shouldn't be set on return.

                        (RtlCompareUnicodeString(
                            &(All->FullName),
                            &(All2->FullName),
                            FALSE) != 0) ||
                        (RtlCompareUnicodeString(
                            &(All->HomeDirectory),
                            &(All2->HomeDirectory),
                            FALSE) != 0) ||
                        (RtlCompareUnicodeString(
                            &(All->HomeDirectoryDrive),
                            &(All2->HomeDirectoryDrive),
                            FALSE) != 0) ||
                        (RtlCompareUnicodeString(
                            &(All->ScriptPath),
                            &(All2->ScriptPath),
                            FALSE) != 0) ||
                        (RtlCompareUnicodeString(
                            &(All->ProfilePath),
                            &(All2->ProfilePath),
                            FALSE) != 0) ||
                        (RtlCompareUnicodeString(
                            &(All->AdminComment),
                            &(All2->AdminComment),
                            FALSE) != 0) ||
                        (RtlCompareUnicodeString(
                            &(All->WorkStations),
                            &(All2->WorkStations),
                            FALSE) != 0) ||
                        (RtlCompareUnicodeString(
                            &(All->UserComment),
                            &(All2->UserComment),
                            FALSE) != 0) ||
                        (RtlCompareUnicodeString(
                            &(All->Parameters),
                            &(All2->Parameters),
                            FALSE) != 0) ||
                        ( All->CountryCode != All2->CountryCode ) ||
                        ( All->CodePage != All2->CodePage ) ||
                        ( All->LmPasswordPresent != All2->LmPasswordPresent ) ||
                        ( All->NtPasswordPresent == All2->NtPasswordPresent ) ||
                        ( All->LogonHours.UnitsPerWeek !=
                            All2->LogonHours.UnitsPerWeek )
                        ) {

                        NtStatus = STATUS_DATA_ERROR;
                    }

                    SamFreeMemory( All2 );
                }
            }

            SamFreeMemory( All );
        }

        if (NtStatus == STATUS_SUCCESS) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }

        //
        // Now get rid of the user account if necessary
        //

        NtStatus = SamDeleteUser( UserHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));
#endif //BROKEN


        printf("      Set Primary Group (non member). . . . . . . . . . . .     ");
        //
        // The following user might already exist (from earlier in the test)
        //

        RtlInitString( &AccountNameAnsi, USER_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );


        UserRid = 0;
        UserHandle1 = NULL;
        NtStatus = SamCreateUserInDomain(
                       DomainHandle,
                       &AccountName,
                       USER_ALL_ACCESS,
                       &UserHandle1,
                       &UserRid
                       );
        RtlFreeUnicodeString( &AccountName );
        DeleteUser = TRUE;
        if (NtStatus == STATUS_USER_EXISTS) {
            DeleteUser = FALSE;
            RtlInitString( &AccountNameAnsi, USER_NAME1 );
            NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
            TST_SUCCESS_ASSERT(NtStatus);

            NtStatus = SamLookupNamesInDomain(
                           DomainHandle,
                           1,
                           &AccountNames[0],
                           &LookedUpRids,
                           &LookedUpUses
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(LookedUpUses[0] == SidTypeUser);
            RtlFreeUnicodeString( &AccountNames[0] );
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_ALL_ACCESS,
                           LookedUpRids[0],
                           &UserHandle1);
            SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );
        }

        ASSERT(NT_SUCCESS(NtStatus));


        //
        // The user is not a member of DOMAIN_GROUP_RID_ADMINS.
        // See if we can make this group the user's primary group
        //

        ASSERT(sizeof(GroupRid) == sizeof(USER_PRIMARY_GROUP_INFORMATION));
        GroupRid = DOMAIN_GROUP_RID_ADMINS;
        NtStatus = SamSetInformationUser(
                       UserHandle1,
                       UserPrimaryGroupInformation,
                       &GroupRid
                       );

        if (NtStatus == STATUS_MEMBER_NOT_IN_GROUP) {

            printf("Succeeded\n");

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        //
        // Now get rid of the user account if necessary
        //

        if (DeleteUser == TRUE) {
            NtStatus = SamDeleteUser( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        } else {
            NtStatus = SamCloseHandle( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        }



        printf("      Set Primary Group (member). . . . . . . . . . . . . .     ");

        //
        // Make a user (might already exist)
        // Make a group
        // Make the group the user's primary group
        // Change the user so the group isn't the primary group
        // remove the group
        // delete the group
        // If we created the user, delete it.

        //
        // The following user might already exist (from earlier in the test)
        //

        RtlInitString( &AccountNameAnsi, USER_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );

        UserRid = 0;
        UserHandle1 = NULL;
        NtStatus = SamCreateUserInDomain(
                       DomainHandle,
                       &AccountName,
                       USER_ALL_ACCESS,
                       &UserHandle1,
                       &UserRid
                       );
        RtlFreeUnicodeString( &AccountName );
        DeleteUser = TRUE;
        if (NtStatus == STATUS_USER_EXISTS) {
            DeleteUser = FALSE;
            RtlInitString( &AccountNameAnsi, USER_NAME1 );
            NtStatus = RtlAnsiStringToUnicodeString( &AccountNames[0], &AccountNameAnsi, TRUE );
            TST_SUCCESS_ASSERT(NtStatus);

            NtStatus = SamLookupNamesInDomain(
                           DomainHandle,
                           1,
                           &AccountNames[0],
                           &LookedUpRids,
                           &LookedUpUses
                           );
            RtlFreeUnicodeString( &AccountNames[0] );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(LookedUpUses[0] == SidTypeUser);
            UserRid = LookedUpRids[0];
            NtStatus = SamOpenUser(
                           DomainHandle,
                           USER_ALL_ACCESS,
                           UserRid,
                           &UserHandle1);
            SamFreeMemory( LookedUpUses ); SamFreeMemory( LookedUpRids );
        }

        ASSERT(NT_SUCCESS(NtStatus));


        //
        // create the group
        //

        RtlInitString( &AccountNameAnsi, GROUP_NAME1 );
        NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi, TRUE );
        TST_SUCCESS_ASSERT(NtStatus);

        //InitializeObjectAttributes( &ObjectAttributes, &AccountName, 0, 0, NULL );

        GroupRid = 0;
        GroupHandle1 = NULL;
        NtStatus = SamCreateGroupInDomain(
                       DomainHandle,
                       &AccountName,
                       GROUP_ALL_ACCESS,
                       &GroupHandle1,
                       &GroupRid
                       );
        RtlFreeUnicodeString( &AccountName );
        ASSERT(NT_SUCCESS(NtStatus));

        //
        // Make the user a member of this group
        //

        NtStatus = SamAddMemberToGroup(
                       GroupHandle1,
                       UserRid,
                       SE_GROUP_MANDATORY              |
                           SE_GROUP_ENABLED_BY_DEFAULT |
                           SE_GROUP_ENABLED
                       );
        ASSERT(NT_SUCCESS(NtStatus));


        //
        // Set the user's primary group Id to be this group
        //

        NtStatus = SamSetInformationUser(
                       UserHandle1,
                       UserPrimaryGroupInformation,
                       &GroupRid
                       );
        if (NT_SUCCESS(NtStatus)) {

            Buffer1 = NULL;
            NtStatus = SamQueryInformationUser(
                           UserHandle1,
                           UserPrimaryGroupInformation,
                           &Buffer1
                           );
            TST_SUCCESS_ASSERT(NtStatus);
            ASSERT(Buffer1 != NULL);

            if ( ((USER_PRIMARY_GROUP_INFORMATION *)Buffer1)->PrimaryGroupId  ==
                 GroupRid ) {

                printf("Succeeded\n");

                SamFreeMemory( Buffer1 );
            } else {

                printf("Failed\n");
                printf("        Returned Value Doesn't Match Set Value.\n");
                printf("        Value written is: 0x%lx\n", GroupRid);
                printf("      Value retrieved is: 0x%lx\n",
                    ((USER_PRIMARY_GROUP_INFORMATION *)Buffer1)->PrimaryGroupId);
                TestStatus = FALSE;

            }

        } else {
            printf("Failed\n");
            printf("        Completion status is 0x%lx\n", NtStatus);
            TestStatus = FALSE;
        }


        //
        // Set the user's primary group Id back and remove the user
        // from the group
        //

        GroupRid = DOMAIN_GROUP_RID_USERS;
        NtStatus = SamSetInformationUser(
                       UserHandle1,
                       UserPrimaryGroupInformation,
                       &GroupRid
                       );
        ASSERT(NT_SUCCESS(NtStatus));
        NtStatus = SamRemoveMemberFromGroup(GroupHandle1, UserRid);
        ASSERT(NT_SUCCESS(NtStatus));



        //
        // Now get rid of the group and possibly the user account
        //


        NtStatus = SamDeleteGroup( GroupHandle1 );
        ASSERT(NT_SUCCESS(NtStatus));

        if (DeleteUser == TRUE) {
            NtStatus = SamDeleteUser( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        } else {
            NtStatus = SamCloseHandle( UserHandle1 );
            ASSERT(NT_SUCCESS(NtStatus));
        }









        printf("      Set Name Information  . . . . . . . . . . . . . . . .     ");
        printf("(Untested)\n");


    }

    return(TestStatus);

}
#endif // NOT_PART_OF_PROGRAM