3611 lines
92 KiB
C
3611 lines
92 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
almember.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This file contains utilities related to membership of aliases.
|
|||
|
Alternative design
|
|||
|
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Scott Birrell 01-Apr-1993
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode - Win32
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Includes //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
#include <samsrvp.h>
|
|||
|
|
|||
|
#define SAMP_AL_FREE_OLD_LIST ((ULONG) 0x00000001L)
|
|||
|
#define SAMP_AL_ERROR_IF_MEMBER ((ULONG) 0x00000002L)
|
|||
|
#define SAMP_AL_ERROR_IF_NOT_MEMBER ((ULONG) 0x00000004L)
|
|||
|
#define SAMP_AL_ASSIGN_NEW_REFERENCES ((ULONG) 0x00000008L)
|
|||
|
#define SAMP_AL_LOOKUP_BY_SID ((ULONG) 0x00000010L)
|
|||
|
#define SAMP_AL_LOOKUP_BY_REFERENCE ((ULONG) 0x00000020L)
|
|||
|
#define SAMP_AL_VERIFY_NO_ALIASES_IN_ACCOUNT ((ULONG) 0x00000040L)
|
|||
|
#define SAMP_AL_VERIFY_ALL_ALIASES_IN_ACCOUNT ((ULONG) 0x00000080L)
|
|||
|
#define SAMP_AL_VERIFY_NO_MEMBERS_IN_ALIAS ((ULONG) 0x00000100L)
|
|||
|
#define SAMP_AL_VERIFY_ALL_MEMBERS_IN_ALIAS ((ULONG) 0x00000200L)
|
|||
|
|
|||
|
#define SAMP_UNKNOWN_INDEX ((ULONG) 0xffffffffL)
|
|||
|
#define SAMP_AL_ALIAS_LIST_DELTA ((ULONG) 0x00000100L)
|
|||
|
#define SAMP_AL_ALIAS_DELTA ((ULONG) 0x00000040L)
|
|||
|
#define SAMP_AL_REFERENCED_DOMAIN_LIST_DELTA ((ULONG) 0x00000100L)
|
|||
|
#define SAMP_AL_INITIAL_MEMBER_ALIAS_LIST_LENGTH ((ULONG) 0x00001000L)
|
|||
|
#define SAMP_AL_MEMBER_ALIAS_LIST_DELTA ((ULONG) 0x00001000L)
|
|||
|
#define SAMP_AL_INITIAL_REFERENCED_DOMAIN_LIST_LENGTH ((ULONG) 0x00000400L)
|
|||
|
#define SAMP_AL_INITIAL_MEMBER_DOMAIN_LENGTH ((ULONG) 0x00000040L)
|
|||
|
#define SAMP_AL_INITIAL_MEMBER_ACCOUNT_ALIAS_CAPACITY ((ULONG) 0x00000004L)
|
|||
|
#define SAMP_AL_ENUM_PREFERRED_LENGTH ((ULONG) 0x00001000L)
|
|||
|
#define SAMP_AL_INITIAL_MEMBERSHIP_COUNT ((ULONG) 0x0000000aL)
|
|||
|
#define SAMP_AL_MEMBERSHIP_COUNT_DELTA ((ULONG) 0x0000000aL)
|
|||
|
#define SAMP_AL_MEMBER_ALIAS_LIST_SIGNATURE ((ULONG) 0x53494c41)
|
|||
|
#define SAMP_AL_MEMBER_DOMAIN_SIGNATURE ((ULONG) 0x4d4f444d)
|
|||
|
#define SAMP_AL_MEMBER_ACCOUNT_SIGNATURE ((ULONG) 0x4343414d)
|
|||
|
|
|||
|
#define SAMP_AL_DR_ALIAS_LIST_KEY_NAME L"Aliases\\Members\\AliasList"
|
|||
|
#define SAMP_AL_DR_REFERENCED_DOMAIN_LIST_KEY_NAME \
|
|||
|
L"Aliases\\Members\\ReferencedDomainList"
|
|||
|
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Private macro functions //
|
|||
|
// //
|
|||
|
/////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
#define SampAlFirstMemberDomain( MemberAliasList ) \
|
|||
|
(MemberAliasList->MemberDomains)
|
|||
|
|
|||
|
#define SampAlOffsetFirstMemberDomain( MemberAliasList ) \
|
|||
|
(((PUCHAR) SampAlFirstMemberDomain(MemberAliasList)) - ((PUCHAR) MemberAliasList))
|
|||
|
|
|||
|
#define SampAlFirstMemberAccount( MemberDomain ) \
|
|||
|
((PSAMP_AL_MEMBER_ACCOUNT) \
|
|||
|
(((PUCHAR) &((MemberDomain)->DomainSid)) + RtlLengthSid(&((MemberDomain)->DomainSid))))
|
|||
|
|
|||
|
#define SampAlOffsetFirstMemberAccount( MemberDomain ) \
|
|||
|
(((PUCHAR) SampAlFirstMemberAccount(MemberDomain)) - ((PUCHAR) MemberDomain))
|
|||
|
|
|||
|
#define SampAlNextMemberAccount( MemberAccount ) \
|
|||
|
((PSAMP_AL_MEMBER_ACCOUNT)(((PUCHAR) MemberAccount) + (MemberAccount)->MaximumLength))
|
|||
|
|
|||
|
#define SampAlOffsetFirstAlias( OutputMemberAccount ) \
|
|||
|
((ULONG) FIELD_OFFSET(SAMP_AL_MEMBER_ACCOUNT, AliasRids))
|
|||
|
|
|||
|
#define SampAlNextMemberDomain( MemberDomain ) \
|
|||
|
((PSAMP_AL_MEMBER_DOMAIN)(((PUCHAR) MemberDomain) + (MemberDomain)->MaximumLength))
|
|||
|
|
|||
|
#define SampAlNextNewAliasInMemberAccount( MemberAccount ) \
|
|||
|
((PULONG)(((PUCHAR) MemberAccount) + (MemberAccount)->UsedLength))
|
|||
|
|
|||
|
#define SampAlNextNewMemberAccount( MemberDomain ) \
|
|||
|
((PSAMP_AL_MEMBER_ACCOUNT)(((PUCHAR) MemberDomain) + (MemberDomain)->UsedLength))
|
|||
|
|
|||
|
#define SampAlNextNewMemberDomain( MemberAliasList ) \
|
|||
|
((PSAMP_AL_MEMBER_DOMAIN)(((PUCHAR) MemberAliasList) + (MemberAliasList)->UsedLength))
|
|||
|
|
|||
|
#define SampAlInfoIsValid(DomainIndex) \
|
|||
|
((SampDefinedDomains[DomainIndex].AliasInformation.Valid) || \
|
|||
|
(SampServiceState == SampServiceInitializing ))
|
|||
|
|
|||
|
#define SampAlInfoMakeValid(DomainIndex) \
|
|||
|
(SampDefinedDomains[DomainIndex].AliasInformation.Valid = TRUE)
|
|||
|
|
|||
|
#define SampAlInfoMakeInvalid(DomainIndex) \
|
|||
|
(SampDefinedDomains[DomainIndex].AliasInformation.Valid = FALSE)
|
|||
|
|
|||
|
#define SampAlDomainIndexToMemberAliasList( DomainIndex ) \
|
|||
|
((PSAMP_AL_MEMBER_ALIAS_LIST) \
|
|||
|
SampDefinedDomains[ DomainIndex].AliasInformation.MemberAliasList)
|
|||
|
|
|||
|
#define SampAlDomainHandleToMemberAliasList( DomainHandle ) \
|
|||
|
(SampAlDomainIndexToMemberAliasList(((PSAMP_OBJECT) DomainHandle)->DomainIndex))
|
|||
|
|
|||
|
#define SampAlAliasHandleToMemberAliasList( AliasHandle ) \
|
|||
|
(SampAlDomainIndexToMemberAliasList(((PSAMP_OBJECT) AliasHandle)->DomainIndex))
|
|||
|
|
|||
|
#define SampAlMemberDomainToOffset( MemberAliasList, MemberDomain) \
|
|||
|
(((PUCHAR) MemberDomain) - ((PUCHAR) MemberAliasList))
|
|||
|
|
|||
|
#define SampAlMemberDomainFromOffset( MemberDomain, MemberDomainOffset) \
|
|||
|
((PSAMP_AL_MEMBER_DOMAIN)(((PUCHAR) MemberDomain) + MemberDomainOffset))
|
|||
|
|
|||
|
#define SampAlMemberAccountToOffset( MemberDomain, MemberAccount) \
|
|||
|
(((PUCHAR) MemberAccount) - ((PUCHAR) MemberDomain))
|
|||
|
|
|||
|
#define SampAlMemberAccountFromOffset( MemberDomain, MemberAccountOffset) \
|
|||
|
((PSAMP_AL_MEMBER_ACCOUNT)(((PUCHAR) MemberDomain) + MemberAccountOffset))
|
|||
|
|
|||
|
#define SampAlLengthRequiredMemberAccount( AliasCapacity ) \
|
|||
|
(sizeof(SAMP_AL_MEMBER_ACCOUNT) + ((AliasCapacity - 1) * sizeof(ULONG)))
|
|||
|
|
|||
|
#define SampAlUpdateMemberAliasList( AliasHandle, MemberAliasList ) \
|
|||
|
{ \
|
|||
|
PSAMP_OBJECT InternalAliasHandle = (PSAMP_OBJECT) AliasHandle; \
|
|||
|
SampDefinedDomains[InternalAliasHandle->DomainIndex].AliasInformation.MemberAliasList \
|
|||
|
= MemberAliasList; \
|
|||
|
}
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Private Datatypes //
|
|||
|
// //
|
|||
|
/////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
// This datatype is not currently used. It may be used if Alias information
|
|||
|
// is every stored to Registry Keys.
|
|||
|
//
|
|||
|
|
|||
|
typedef enum _SAMP_AL_LIST_TYPE {
|
|||
|
|
|||
|
SampAlMemberAliasList = 1
|
|||
|
|
|||
|
} SAMP_AL_LIST_TYPE, *PSAMP_AL_LIST_TYPE;
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Private Static Data //
|
|||
|
// //
|
|||
|
/////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
UNICODE_STRING SampAlDrMemberAliasListKeyName;
|
|||
|
BOOLEAN SampAlEnableBuildingOfList[SAMP_DEFINED_DOMAINS_COUNT] = { TRUE, TRUE };
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Prototypes of functions private to this module //
|
|||
|
// //
|
|||
|
/////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlCreateMemberAliasList(
|
|||
|
IN LONG DomainIndex,
|
|||
|
IN ULONG InitialMemberAliasListLength,
|
|||
|
OUT OPTIONAL PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlGrowMemberAliasList(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN ULONG ExtraSpaceRequired
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlBuildMemberAliasList(
|
|||
|
IN LONG DomainIndex
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlCreateMemberDomain(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSID DomainSid,
|
|||
|
OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlAllocateMemberDomain(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN ULONG MaximumLengthMemberDomain,
|
|||
|
OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlGrowMemberDomain(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN ULONG ExtraSpaceRequired
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlDeleteMemberDomain(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlLookupMemberDomain(
|
|||
|
IN PSAMP_AL_MEMBER_ALIAS_LIST MemberAliasList,
|
|||
|
IN PSID DomainSid,
|
|||
|
OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlCreateMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN ULONG Rid,
|
|||
|
IN ULONG AliasCapacity,
|
|||
|
OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlAllocateMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN ULONG MaximumLengthMemberAccount,
|
|||
|
OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlGrowMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount,
|
|||
|
IN ULONG ExtraSpaceRequired
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlDeleteMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN OUT PSAMP_AL_MEMBER_ACCOUNT MemberAccount,
|
|||
|
OUT PBOOLEAN MemberDomainDeleted
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlLookupMemberAccount(
|
|||
|
IN PSAMP_AL_MEMBER_DOMAIN MemberDomain,
|
|||
|
IN ULONG MemberRid,
|
|||
|
OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlAddAliasesToMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount,
|
|||
|
IN ULONG Options,
|
|||
|
IN PSAMPR_ULONG_ARRAY AliasRids
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlRemoveAliasesFromMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount,
|
|||
|
IN ULONG Options,
|
|||
|
IN PSAMPR_ULONG_ARRAY AliasRids,
|
|||
|
OUT PBOOLEAN MemberDomainDeleted,
|
|||
|
OUT PBOOLEAN MemberAccountDeleted
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlLookupAliasesInMemberAccount(
|
|||
|
IN PSAMP_AL_MEMBER_ACCOUNT MemberAccount,
|
|||
|
IN PSAMPR_ULONG_ARRAY AliasRids,
|
|||
|
OUT PULONG ExistingAliasCount
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlSplitMemberSids(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN ULONG Options,
|
|||
|
IN PSAMPR_PSID_ARRAY MemberSids,
|
|||
|
OUT PSAMP_AL_SPLIT_MEMBER_SID_LIST SplitMemberSids
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SampAlInfoIsValidForDomain(
|
|||
|
IN SAMPR_HANDLE DomainHandle
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SampAlInfoIsValidForAlias(
|
|||
|
IN SAMPR_HANDLE AliasHandle
|
|||
|
);
|
|||
|
|
|||
|
//////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Code of Exported Routines //
|
|||
|
// //
|
|||
|
//////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SamrGetAliasMembership(
|
|||
|
IN SAMPR_HANDLE DomainHandle,
|
|||
|
IN PSAMPR_PSID_ARRAY SidArray,
|
|||
|
OUT PSAMPR_ULONG_ARRAY Membership
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This API searches the set of aliases in the specified domain to see
|
|||
|
which aliases, if any, the passed SIDs are members of. Any aliases
|
|||
|
that any of the SIDs are found to be members of are returned.
|
|||
|
|
|||
|
Note that any particular alias will appear only once in the returned list.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
DomainHandle - Handle from a SamOpenDomain call.
|
|||
|
|
|||
|
PassedCount - Specifies the number of Sids being passed.
|
|||
|
|
|||
|
Sids - Pointer to an arrray of Count pointers to Sids whose alias
|
|||
|
memberships are to be looked up.
|
|||
|
|
|||
|
Membership - receives the array of rids rerpresenting the aliases
|
|||
|
in this domain that any of the sid(s) are members of.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
STATUS_SUCCESS - The combined alias membership is in Membership
|
|||
|
|
|||
|
STATUS_INVALID_SID - One of the passed sids was invalid
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS NtStatus, IgnoreStatus;
|
|||
|
PSAMP_OBJECT DomainContext;
|
|||
|
SAMP_OBJECT_TYPE FoundType;
|
|||
|
ULONG i;
|
|||
|
ULONG SidCount;
|
|||
|
PSID *Sids;
|
|||
|
BOOLEAN ObjectReferenced = FALSE;
|
|||
|
|
|||
|
ASSERT(Membership != NULL);
|
|||
|
ASSERT(Membership->Element == NULL);
|
|||
|
|
|||
|
SidCount = SidArray->Count;
|
|||
|
Sids = (PSID *)(SidArray->Sids);
|
|||
|
|
|||
|
//
|
|||
|
// Grab the lock
|
|||
|
//
|
|||
|
|
|||
|
SampAcquireReadLock();
|
|||
|
|
|||
|
//
|
|||
|
// Validate type of, and access to object.
|
|||
|
//
|
|||
|
|
|||
|
DomainContext = (PSAMP_OBJECT)DomainHandle;
|
|||
|
|
|||
|
NtStatus = SampLookupContext(
|
|||
|
DomainContext,
|
|||
|
DOMAIN_LOOKUP,
|
|||
|
SampDomainObjectType,
|
|||
|
&FoundType
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtStatus)) {
|
|||
|
|
|||
|
goto GetAliasMembershipError;
|
|||
|
}
|
|||
|
|
|||
|
ObjectReferenced = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// Validate the Sids. if any are invalid, return an error.
|
|||
|
//
|
|||
|
|
|||
|
for (i=0; i < SidCount; i++) {
|
|||
|
|
|||
|
//
|
|||
|
// Check for valid sid
|
|||
|
//
|
|||
|
|
|||
|
if ( (Sids[i] == NULL) || !RtlValidSid(Sids[i]) ) {
|
|||
|
|
|||
|
NtStatus = STATUS_INVALID_SID;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtStatus)) {
|
|||
|
|
|||
|
goto GetAliasMembershipError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the in-memory Alias Membership information for this domain is valid,
|
|||
|
// use it to retrieve the Alias members.
|
|||
|
//
|
|||
|
|
|||
|
if (SampAlInfoIsValidForDomain(DomainHandle)) {
|
|||
|
|
|||
|
NtStatus = SampAlQueryAliasMembership(
|
|||
|
DomainHandle,
|
|||
|
SidArray,
|
|||
|
Membership
|
|||
|
);
|
|||
|
} else {
|
|||
|
|
|||
|
NtStatus = SampAlSlowQueryAliasMembership(
|
|||
|
DomainHandle,
|
|||
|
SidArray,
|
|||
|
Membership
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
GetAliasMembershipFinish:
|
|||
|
|
|||
|
//
|
|||
|
// If necessary, dereference the SAM server object.
|
|||
|
//
|
|||
|
|
|||
|
if (ObjectReferenced) {
|
|||
|
|
|||
|
IgnoreStatus = SampDeReferenceContext( DomainContext, FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Free the read lock
|
|||
|
//
|
|||
|
|
|||
|
SampReleaseReadLock();
|
|||
|
|
|||
|
return(NtStatus);
|
|||
|
|
|||
|
GetAliasMembershipError:
|
|||
|
|
|||
|
goto GetAliasMembershipFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlQueryAliasMembership(
|
|||
|
IN SAMPR_HANDLE DomainHandle,
|
|||
|
IN PSAMPR_PSID_ARRAY SidArray,
|
|||
|
OUT PSAMPR_ULONG_ARRAY Membership
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is one of two worker routines for the SamrGetAliasMembership
|
|||
|
API. This worker uses the Member Alias List to determine which aliases,
|
|||
|
if any, the passed SIDs are members of. Any aliases that any of the SIDs
|
|||
|
are found to be members of are returned.
|
|||
|
|
|||
|
Note that any particular alias will appear only once in the returned list.
|
|||
|
|
|||
|
See also SampAlSlowQueryAliasMembership()
|
|||
|
|
|||
|
WARNING: The SAM Read Lock must be held while this function executes.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
DomainHandle - Handle from a SamrOpenDomain call.
|
|||
|
|
|||
|
SidArray - Pointer to a counted array of pointers to Sids whose alias
|
|||
|
memberships are to be looked up.
|
|||
|
|
|||
|
Membership - Receives the array of rids rerpresenting the aliases
|
|||
|
in this domain that any of the sid(s) are members of.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
STATUS_SUCCESS - The combined alias membership is in Membership
|
|||
|
|
|||
|
STATUS_INVALID_SID - One of the passed sids was invalid
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
PSAMP_AL_MEMBER_ALIAS_LIST MemberAliasList = NULL;
|
|||
|
PSAMP_AL_MEMBER_DOMAIN MemberDomain = NULL;
|
|||
|
ULONG Rid, AliasRid;
|
|||
|
ULONG AliasIndex, SidIndex;
|
|||
|
PSAMP_AL_MEMBER_ACCOUNT MemberAccount = NULL;
|
|||
|
BOOLEAN AliasAlreadyFound;
|
|||
|
ULONG AliasFoundIndex, MembershipMaximumCount;
|
|||
|
PSID DomainSid = NULL;
|
|||
|
PSID Sid = NULL;
|
|||
|
PULONG NewMembership = NULL;
|
|||
|
|
|||
|
Membership->Count = 0;
|
|||
|
Membership->Element = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Obtain pointer to Alias Member List.
|
|||
|
//
|
|||
|
|
|||
|
MemberAliasList = SampAlDomainHandleToMemberAliasList( DomainHandle );
|
|||
|
|
|||
|
//
|
|||
|
// If there are no Member Domains in this Member Alias List, then just
|
|||
|
// finish.
|
|||
|
//
|
|||
|
|
|||
|
if (MemberAliasList->DomainCount == 0) {
|
|||
|
|
|||
|
goto QueryAliasMembershipFinish;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Allocate Scratch Sid buffer. We will use this same buffer for splitting
|
|||
|
// each Sid.
|
|||
|
//
|
|||
|
|
|||
|
DomainSid = MIDL_user_allocate( RtlLengthRequiredSid( 256 ));
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
|
|||
|
if (DomainSid == NULL) {
|
|||
|
|
|||
|
goto QueryAliasMembershipError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate output array with a nominal initial size. Reallocate it
|
|||
|
// as necessary
|
|||
|
//
|
|||
|
|
|||
|
MembershipMaximumCount = SAMP_AL_INITIAL_MEMBERSHIP_COUNT;
|
|||
|
|
|||
|
Membership->Element = MIDL_user_allocate( MembershipMaximumCount * sizeof(ULONG));
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
|
|||
|
if (Membership->Element == NULL) {
|
|||
|
|
|||
|
goto QueryAliasMembershipError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// Now query the membership of the array of split Sids. For each
|
|||
|
// Sid, we skip the Sid if it has an unknown MemberDomain, because
|
|||
|
// it does not belong to any aliases. For each surviving Sid, we scan the
|
|||
|
// Alias List, skipping entries for aliases we've already entered in the
|
|||
|
// output list. We search for the Rid only in the section of the
|
|||
|
// Alias List pertinent to the Sid's domain.
|
|||
|
//
|
|||
|
|
|||
|
for (SidIndex = 0; SidIndex < SidArray->Count; SidIndex++) {
|
|||
|
|
|||
|
Sid = SidArray->Sids[ SidIndex ].SidPointer;
|
|||
|
|
|||
|
//
|
|||
|
// Split this Sid into a DomainSid and a Rid. Note that we re-use
|
|||
|
// the buffer containing the Domain Sid for the next Sid.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampSplitSid( Sid, &DomainSid, &Rid);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Search the Member Alias List for the Sid's Member Domain
|
|||
|
// (if any).
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlLookupMemberDomain(
|
|||
|
MemberAliasList,
|
|||
|
DomainSid,
|
|||
|
&MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
//
|
|||
|
// The only expected error is STATUS_NO_SUCH_DOMAIN. If we
|
|||
|
// don't get this error, fail the request. Otherwise, the
|
|||
|
// Sid is not a member of any aliases in the SAM local domain, so
|
|||
|
// just skip to the next Sid.
|
|||
|
//
|
|||
|
|
|||
|
if (Status != STATUS_NO_SUCH_DOMAIN) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We've found the Member Domain. Now find the Member Account.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlLookupMemberAccount(
|
|||
|
MemberDomain,
|
|||
|
Rid,
|
|||
|
&MemberAccount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
//
|
|||
|
// The only expected error is STATUS_NO_SUCH_MEMBER. If we
|
|||
|
// don't get this error, fail the request. Otherwise, the
|
|||
|
// Sid is not a member of any aliases in the domain, so just
|
|||
|
// skip to the next Sid.
|
|||
|
//
|
|||
|
|
|||
|
if (Status != STATUS_NO_SUCH_MEMBER) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We've found the Member Account. For each of the aliases our Sid
|
|||
|
// belongs to, add the alias to the output list if not already there.
|
|||
|
//
|
|||
|
|
|||
|
for (AliasIndex = 0; AliasIndex < MemberAccount->AliasCount; AliasIndex++) {
|
|||
|
|
|||
|
AliasRid = MemberAccount->AliasRids[AliasIndex];
|
|||
|
|
|||
|
AliasAlreadyFound = FALSE;
|
|||
|
|
|||
|
for (AliasFoundIndex = 0;
|
|||
|
AliasFoundIndex < Membership->Count;
|
|||
|
AliasFoundIndex++) {
|
|||
|
|
|||
|
if (AliasRid == Membership->Element[AliasFoundIndex]) {
|
|||
|
|
|||
|
AliasAlreadyFound = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!AliasAlreadyFound) {
|
|||
|
|
|||
|
//
|
|||
|
// If there isn't enough room in the output Membership
|
|||
|
// array, reallocate it.
|
|||
|
//
|
|||
|
|
|||
|
if (Membership->Count == MembershipMaximumCount) {
|
|||
|
|
|||
|
MembershipMaximumCount += SAMP_AL_MEMBERSHIP_COUNT_DELTA;
|
|||
|
|
|||
|
NewMembership = MIDL_user_allocate(
|
|||
|
MembershipMaximumCount * sizeof(ULONG)
|
|||
|
);
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
|
|||
|
if (NewMembership == NULL) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
RtlMoveMemory(
|
|||
|
NewMembership,
|
|||
|
Membership->Element,
|
|||
|
Membership->Count * sizeof(ULONG)
|
|||
|
);
|
|||
|
|
|||
|
MIDL_user_free( Membership->Element);
|
|||
|
Membership->Element = NewMembership;
|
|||
|
}
|
|||
|
|
|||
|
Membership->Element[Membership->Count] = AliasRid;
|
|||
|
Membership->Count++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the buffer we've allocated turns out to be way overboard, allocate
|
|||
|
// a smaller one for the output.
|
|||
|
//
|
|||
|
|
|||
|
// TBS
|
|||
|
|
|||
|
QueryAliasMembershipFinish:
|
|||
|
|
|||
|
//
|
|||
|
// If we got as far as allocating a buffer for the DomainSids, free it.
|
|||
|
//
|
|||
|
|
|||
|
if (DomainSid != NULL) {
|
|||
|
|
|||
|
MIDL_user_free(DomainSid);
|
|||
|
DomainSid = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
QueryAliasMembershipError:
|
|||
|
|
|||
|
//
|
|||
|
// If necessary, free the output membership array.
|
|||
|
//
|
|||
|
|
|||
|
if (Membership->Element != NULL) {
|
|||
|
|
|||
|
MIDL_user_free( Membership->Element);
|
|||
|
Membership->Element = NULL;
|
|||
|
}
|
|||
|
|
|||
|
goto QueryAliasMembershipFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlSlowQueryAliasMembership(
|
|||
|
IN SAMPR_HANDLE DomainHandle,
|
|||
|
IN PSAMPR_PSID_ARRAY SidArray,
|
|||
|
OUT PSAMPR_ULONG_ARRAY Membership
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is the slow version of the worker routine for the
|
|||
|
SamrGetAliasMembership API searches. It is called when the in-memory
|
|||
|
Alias Information is no longer valid.
|
|||
|
|
|||
|
WARNING! The caller of this function must hold the SAM Database Read
|
|||
|
Lock.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
DomainHandle - Handle from a SamOpenDomain call.
|
|||
|
|
|||
|
SidArray - Pointer to a counted array of pointers to Sids whose alias
|
|||
|
memberships are to be looked up.
|
|||
|
|
|||
|
Membership - Receives the array of rids rerpresenting the aliases
|
|||
|
in this domain that any of the sid(s) are members of.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
STATUS_SUCCESS - The combined alias membership is in Membership
|
|||
|
|
|||
|
STATUS_INVALID_SID - One of the passed sids was invalid
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS NtStatus;
|
|||
|
ULONG i;
|
|||
|
ULONG MembershipCount;
|
|||
|
ULONG TotalMembershipCount;
|
|||
|
ULONG MembershipIndex;
|
|||
|
ULONG BufferSize;
|
|||
|
ULONG TotalBufferSize;
|
|||
|
ULONG SidCount = SidArray->Count;
|
|||
|
PSID *Sids = (PSID *) &SidArray->Sids->SidPointer;
|
|||
|
|
|||
|
//
|
|||
|
// For each Sid, retrieve its membership and size up how many membership
|
|||
|
// entries we'll have in total.
|
|||
|
//
|
|||
|
|
|||
|
TotalMembershipCount = 0;
|
|||
|
TotalBufferSize = 0;
|
|||
|
|
|||
|
for (i=0; i < SidCount; i++) {
|
|||
|
|
|||
|
//
|
|||
|
// Get the membership count for this account
|
|||
|
//
|
|||
|
|
|||
|
BufferSize = 0;
|
|||
|
|
|||
|
NtStatus = SampRetrieveAliasMembership(
|
|||
|
Sids[i],
|
|||
|
&MembershipCount,
|
|||
|
&BufferSize,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
if (NT_SUCCESS(NtStatus) || (NtStatus == STATUS_BUFFER_OVERFLOW)) {
|
|||
|
|
|||
|
ASSERT(BufferSize == (MembershipCount * sizeof(ULONG)));
|
|||
|
|
|||
|
TotalMembershipCount += MembershipCount;
|
|||
|
TotalBufferSize += BufferSize;
|
|||
|
|
|||
|
NtStatus = STATUS_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Allocate and fill in the membership array
|
|||
|
//
|
|||
|
|
|||
|
if (NT_SUCCESS(NtStatus)) {
|
|||
|
|
|||
|
Membership->Element = MIDL_user_allocate(TotalBufferSize);
|
|||
|
|
|||
|
if (Membership->Element == NULL) {
|
|||
|
|
|||
|
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the allocated membership list
|
|||
|
//
|
|||
|
|
|||
|
MembershipIndex = 0;
|
|||
|
|
|||
|
for (i=0; i < SidCount; i++) {
|
|||
|
|
|||
|
//
|
|||
|
// Get the membership list for this account
|
|||
|
//
|
|||
|
|
|||
|
BufferSize = TotalBufferSize;
|
|||
|
|
|||
|
NtStatus = SampRetrieveAliasMembership(
|
|||
|
Sids[i],
|
|||
|
&MembershipCount,
|
|||
|
&BufferSize,
|
|||
|
&(Membership->Element[MembershipIndex])
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtStatus)) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT(BufferSize == (MembershipCount * sizeof(*(Membership->Element))));
|
|||
|
|
|||
|
//
|
|||
|
// Remove duplicate aliases
|
|||
|
//
|
|||
|
|
|||
|
if (MembershipCount > 0) {
|
|||
|
|
|||
|
ULONG ExistingIndex, NewIndex;
|
|||
|
|
|||
|
for (ExistingIndex = 0; ExistingIndex < MembershipIndex; ExistingIndex ++) {
|
|||
|
|
|||
|
for (NewIndex = MembershipIndex; NewIndex < MembershipIndex + MembershipCount; NewIndex ++) {
|
|||
|
|
|||
|
if (Membership->Element[ExistingIndex] ==
|
|||
|
Membership->Element[NewIndex]) {
|
|||
|
|
|||
|
//
|
|||
|
// This alias is already in the list - forget it
|
|||
|
//
|
|||
|
|
|||
|
if (NewIndex < MembershipIndex + MembershipCount - 1) {
|
|||
|
|
|||
|
//
|
|||
|
// Remove the duplicate alias
|
|||
|
//
|
|||
|
|
|||
|
Membership->Element[NewIndex] =
|
|||
|
Membership->Element[MembershipIndex + MembershipCount - 1];
|
|||
|
|
|||
|
NewIndex --; // So we come back to this alias again
|
|||
|
}
|
|||
|
|
|||
|
MembershipCount --;
|
|||
|
TotalMembershipCount --;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
MembershipIndex += MembershipCount;
|
|||
|
|
|||
|
ASSERT(MembershipIndex <= TotalMembershipCount);
|
|||
|
ASSERT(TotalBufferSize >= BufferSize);
|
|||
|
|
|||
|
TotalBufferSize -= BufferSize;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtStatus)) {
|
|||
|
MIDL_user_free(Membership->Element);
|
|||
|
Membership->Element = NULL;
|
|||
|
} else {
|
|||
|
Membership->Count = TotalMembershipCount;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return NtStatus;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlQueryMembersOfAlias(
|
|||
|
IN SAMPR_HANDLE AliasHandle,
|
|||
|
OUT PSAMPR_PSID_ARRAY MemberSids
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function returns an array of Sids of accounts that are members of
|
|||
|
a specified alias.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AliasHandle - Handle to an Alias object
|
|||
|
|
|||
|
MemberSids - Receives an array of Sids that belong to the Alias
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PSAMP_AL_ALIAS_MEMBER_LIST AliasMemberList = NULL;
|
|||
|
PSID *Members = NULL;
|
|||
|
ULONG AliasMemberCount;
|
|||
|
|
|||
|
Status = SampRetrieveAliasMembers(
|
|||
|
AliasHandle,
|
|||
|
&AliasMemberCount,
|
|||
|
&Members
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto QueryMembersOfAliasError;
|
|||
|
}
|
|||
|
|
|||
|
QueryMembersOfAliasFinish:
|
|||
|
|
|||
|
MemberSids->Count = AliasMemberCount;
|
|||
|
MemberSids->Sids = (PSAMPR_SID_INFORMATION) Members;
|
|||
|
return(Status);
|
|||
|
|
|||
|
QueryMembersOfAliasError:
|
|||
|
|
|||
|
AliasMemberCount = 0;
|
|||
|
Members = NULL;
|
|||
|
goto QueryMembersOfAliasFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlAddMembersToAlias(
|
|||
|
IN SAMPR_HANDLE AliasHandle,
|
|||
|
IN ULONG Options,
|
|||
|
IN PSAMPR_PSID_ARRAY MemberSids
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function adds one or more member to an alias. Any failure results
|
|||
|
in the in-memory Alias Information being discarded.
|
|||
|
|
|||
|
WARNING: The calling function must perform all parameter validation and
|
|||
|
the SAM Database Write Lock must be held.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
AliasHandle - The handle of an opened alias to operate on.
|
|||
|
|
|||
|
Options - Specifies optional actions to be taken
|
|||
|
|
|||
|
SAMP_AL_VERIFY_NO_MEMBERS_IN_ALIAS - Verify that none of the
|
|||
|
Members are already present in the Alias.
|
|||
|
|
|||
|
MemberSids - Array of member Sids to be added.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
STATUS_SUCCESS - The Service completed successfully.
|
|||
|
|
|||
|
STATUS_MEMBER_IN_ALIAS - The member already belongs to the alias.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PSAMP_AL_MEMBER_ALIAS_LIST MemberAliasList = NULL;
|
|||
|
PSAMP_AL_MEMBER_ALIAS_LIST OldMemberAliasList = NULL;
|
|||
|
PSAMP_AL_MEMBER_DOMAIN MemberDomain = NULL;
|
|||
|
PSAMP_AL_MEMBER_ACCOUNT MemberAccount = NULL;
|
|||
|
ULONG AliasRid = ((PSAMP_OBJECT) AliasHandle)->TypeBody.Alias.Rid;
|
|||
|
ULONG MemberRid, SidIndex, MembershipCount;
|
|||
|
PSID DomainSid = NULL;
|
|||
|
PSID MemberSid = NULL;
|
|||
|
SAMPR_ULONG_ARRAY AliasRids;
|
|||
|
|
|||
|
AliasRids.Count = 0;
|
|||
|
AliasRids.Element = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Verify that the cached Alias Membership information is valid.
|
|||
|
//
|
|||
|
|
|||
|
if (!SampAlInfoIsValidForAlias(AliasHandle)) {
|
|||
|
|
|||
|
goto AddMembersToAliasFinish;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If requested, verify that none of members already belong to the alias
|
|||
|
//
|
|||
|
|
|||
|
if (Options & SAMP_AL_VERIFY_NO_MEMBERS_IN_ALIAS) {
|
|||
|
|
|||
|
Status = SampAlLookupMembersInAlias(
|
|||
|
AliasHandle,
|
|||
|
AliasRid,
|
|||
|
MemberSids,
|
|||
|
&MembershipCount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto AddMembersToAliasError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_MEMBER_NOT_IN_ALIAS;
|
|||
|
|
|||
|
if (MembershipCount > 0) {
|
|||
|
|
|||
|
goto AddMembersToAliasError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Allocate Scratch Sid buffer. We will use this same buffer for splitting
|
|||
|
// each Sid.
|
|||
|
//
|
|||
|
|
|||
|
DomainSid = MIDL_user_allocate( RtlLengthRequiredSid( 256 ));
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
|
|||
|
if (DomainSid == NULL) {
|
|||
|
|
|||
|
goto AddMembersToAliasError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// Obtain pointer to Member Alias List.
|
|||
|
//
|
|||
|
|
|||
|
MemberAliasList = SampAlAliasHandleToMemberAliasList( AliasHandle );
|
|||
|
OldMemberAliasList = MemberAliasList;
|
|||
|
|
|||
|
//
|
|||
|
// For each Sid, obtain its DomainSid and Rid. Then lookup its
|
|||
|
// DomainSid to obtain the MemberDomain, creating one if necessary.
|
|||
|
// Then lookup its Rid to obtain its MemberAccount, creating one
|
|||
|
// if necessary. Then add the Alias to the MemebrAccount.
|
|||
|
//
|
|||
|
|
|||
|
for (SidIndex = 0; SidIndex < MemberSids->Count; SidIndex++ ) {
|
|||
|
|
|||
|
MemberSid = MemberSids->Sids[ SidIndex ].SidPointer;
|
|||
|
|
|||
|
Status = SampSplitSid( MemberSid, &DomainSid, &MemberRid );
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Lookup the Member Domain for this DomainSid in the Member Alias
|
|||
|
// List.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlLookupMemberDomain(
|
|||
|
MemberAliasList,
|
|||
|
DomainSid,
|
|||
|
&MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
if (Status != STATUS_NO_SUCH_DOMAIN) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// The Member Domain was not found. Create a new Member Domain
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlCreateMemberDomain(
|
|||
|
&MemberAliasList,
|
|||
|
DomainSid,
|
|||
|
&MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create a Member Account entry.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlCreateMemberAccount(
|
|||
|
&MemberAliasList,
|
|||
|
&MemberDomain,
|
|||
|
MemberRid,
|
|||
|
SAMP_AL_INITIAL_MEMBER_ACCOUNT_ALIAS_CAPACITY,
|
|||
|
&MemberAccount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// We found the domain. This means that we have to lookup
|
|||
|
// each Member Account. If a Member Account does not exist,
|
|||
|
// we'll create one. Note that we may already have one due
|
|||
|
// to this account being a member of another Alias.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlLookupMemberAccount(
|
|||
|
MemberDomain,
|
|||
|
MemberRid,
|
|||
|
&MemberAccount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
if (Status != STATUS_NO_SUCH_MEMBER) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create a Member Account for this Rid,
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlCreateMemberAccount(
|
|||
|
&MemberAliasList,
|
|||
|
&MemberDomain,
|
|||
|
MemberRid,
|
|||
|
SAMP_AL_INITIAL_MEMBER_ACCOUNT_ALIAS_CAPACITY,
|
|||
|
&MemberAccount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We now have a MemberAccount. Now add the Alias to it.
|
|||
|
//
|
|||
|
|
|||
|
AliasRids.Count = 1;
|
|||
|
AliasRids.Element = &AliasRid;
|
|||
|
|
|||
|
Status = SampAlAddAliasesToMemberAccount(
|
|||
|
&MemberAliasList,
|
|||
|
&MemberDomain,
|
|||
|
&MemberAccount,
|
|||
|
0,
|
|||
|
&AliasRids
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Deal with next Member Sid for the Alias.
|
|||
|
//
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto AddMembersToAliasError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the Member Alias List has been reallocated, store its new address.
|
|||
|
//
|
|||
|
|
|||
|
if (MemberAliasList != OldMemberAliasList) {
|
|||
|
|
|||
|
SampAlUpdateMemberAliasList( AliasHandle, MemberAliasList );
|
|||
|
}
|
|||
|
|
|||
|
AddMembersToAliasFinish:
|
|||
|
|
|||
|
//
|
|||
|
// If necessary, free the DomainSid.
|
|||
|
//
|
|||
|
|
|||
|
if (DomainSid != NULL) {
|
|||
|
|
|||
|
MIDL_user_free( DomainSid );
|
|||
|
DomainSid = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
AddMembersToAliasError:
|
|||
|
|
|||
|
goto AddMembersToAliasFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlRemoveMembersFromAlias(
|
|||
|
IN SAMPR_HANDLE AliasHandle,
|
|||
|
IN ULONG Options,
|
|||
|
IN PSAMPR_PSID_ARRAY MemberSids
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function removes a list of members from an Alias.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AliasHandle - The handle of an opened alias to operate on.
|
|||
|
|
|||
|
Options - Specifies optional actions to be taken
|
|||
|
|
|||
|
SAMP_AL_VERIFY_ALL_MEMBERS_IN_ALIAS - Verify that all of the
|
|||
|
Members belong to the Alias.
|
|||
|
|
|||
|
MemberSids - Array of member Sids to be removed.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
STATUS_SUCCESS - The Service completed successfully.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PSAMP_AL_MEMBER_ALIAS_LIST MemberAliasList = NULL;
|
|||
|
PSAMP_AL_MEMBER_ALIAS_LIST OldMemberAliasList = NULL;
|
|||
|
PSAMP_AL_MEMBER_DOMAIN MemberDomain = NULL;
|
|||
|
PSAMP_AL_MEMBER_ACCOUNT MemberAccount = NULL;
|
|||
|
BOOLEAN MemberDomainDeleted;
|
|||
|
BOOLEAN MemberAccountDeleted;
|
|||
|
ULONG AliasRid = ((PSAMP_OBJECT) AliasHandle)->TypeBody.Alias.Rid;
|
|||
|
ULONG MemberRid, SidIndex, MembershipCount;
|
|||
|
PSID DomainSid = NULL;
|
|||
|
PSID MemberSid = NULL;
|
|||
|
SAMPR_ULONG_ARRAY AliasRids;
|
|||
|
|
|||
|
AliasRids.Count = 0;
|
|||
|
AliasRids.Element = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// If requested, verify that all of members already belong to the alias
|
|||
|
//
|
|||
|
|
|||
|
if (Options & SAMP_AL_VERIFY_ALL_MEMBERS_IN_ALIAS) {
|
|||
|
|
|||
|
Status = SampAlLookupMembersInAlias(
|
|||
|
AliasHandle,
|
|||
|
AliasRid,
|
|||
|
MemberSids,
|
|||
|
&MembershipCount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto RemoveMembersFromAliasError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_MEMBER_NOT_IN_ALIAS;
|
|||
|
|
|||
|
if (MembershipCount < MemberSids->Count) {
|
|||
|
|
|||
|
goto RemoveMembersFromAliasError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Obtain pointer to Member Alias List.
|
|||
|
//
|
|||
|
|
|||
|
MemberAliasList = SampAlAliasHandleToMemberAliasList( AliasHandle );
|
|||
|
OldMemberAliasList = MemberAliasList;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto RemoveMembersFromAliasError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// For each Sid, obtain its DomainSid and Rid. Then lookup its
|
|||
|
// DomainSid to obtain the MemberDomain. Then lookup its Rid to obtain
|
|||
|
// its MemberAccount. Then remove the Alias from the MemberAccount.
|
|||
|
//
|
|||
|
|
|||
|
for (SidIndex = 0; SidIndex < MemberSids->Count; SidIndex++ ) {
|
|||
|
|
|||
|
MemberSid = MemberSids->Sids[ SidIndex ].SidPointer;
|
|||
|
|
|||
|
SampSplitSid( MemberSid, &DomainSid, &MemberRid );
|
|||
|
|
|||
|
//
|
|||
|
// Lookup the Member Domain for this DomainSid in the Member Alias
|
|||
|
// List.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlLookupMemberDomain(
|
|||
|
MemberAliasList,
|
|||
|
DomainSid,
|
|||
|
&MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
if (Status != STATUS_MEMBER_NOT_IN_ALIAS) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (Options & SAMP_AL_VERIFY_ALL_MEMBERS_IN_ALIAS) {
|
|||
|
|
|||
|
ASSERT( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We found the domain. This means that we have to lookup
|
|||
|
// each Member Account. If a Member Account does not exist,
|
|||
|
// we'll just skip this account unless we already checked existence.
|
|||
|
// If we checked existence and we can't find it now, its an
|
|||
|
// internal error.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlLookupMemberAccount(
|
|||
|
MemberDomain,
|
|||
|
MemberRid,
|
|||
|
&MemberAccount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
if (Status != STATUS_MEMBER_NOT_IN_ALIAS) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (Options & SAMP_AL_VERIFY_ALL_MEMBERS_IN_ALIAS) {
|
|||
|
|
|||
|
ASSERT( FALSE);
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We now have the MemberAccount. Now remove the Alias from it.
|
|||
|
//
|
|||
|
|
|||
|
AliasRids.Count = 1;
|
|||
|
AliasRids.Element = &AliasRid;
|
|||
|
|
|||
|
Status = SampAlRemoveAliasesFromMemberAccount(
|
|||
|
&MemberAliasList,
|
|||
|
&MemberDomain,
|
|||
|
&MemberAccount,
|
|||
|
0,
|
|||
|
&AliasRids,
|
|||
|
&MemberDomainDeleted,
|
|||
|
&MemberAccountDeleted
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Deal with next Member Sid for the Alias.
|
|||
|
//
|
|||
|
|
|||
|
MIDL_user_free( DomainSid );
|
|||
|
DomainSid = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto RemoveMembersFromAliasError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the Member Alias List has been reallocated, store its new address.
|
|||
|
//
|
|||
|
|
|||
|
if (MemberAliasList != OldMemberAliasList) {
|
|||
|
|
|||
|
SampAlUpdateMemberAliasList( AliasHandle, MemberAliasList );
|
|||
|
}
|
|||
|
|
|||
|
RemoveMembersFromAliasFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
RemoveMembersFromAliasError:
|
|||
|
|
|||
|
goto RemoveMembersFromAliasFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlLookupMembersInAlias(
|
|||
|
IN SAMPR_HANDLE AliasHandle,
|
|||
|
IN ULONG AliasRid,
|
|||
|
IN PSAMPR_PSID_ARRAY MemberSids,
|
|||
|
OUT PULONG MembershipCount
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function checks how many of a given list of Member Sids belong
|
|||
|
to an Alias. It is called prior to updating Alias Memberships.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AliasHandle - Handle to Alias Object
|
|||
|
|
|||
|
AliasRid - Specifies the Rid of the Alias
|
|||
|
|
|||
|
MemberSids - Pointer to counted array of pointers to Member Sids
|
|||
|
|
|||
|
MembershipCount - Receives count of member Sids in the given set
|
|||
|
that belong to the alias.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
SAMPR_PSID_ARRAY AliasMemberSids;
|
|||
|
ULONG OutputMembershipCount = 0;
|
|||
|
ULONG SidIndex, AliasMemberSidIndex;
|
|||
|
PSID Sid = NULL;
|
|||
|
PSID AliasMemberSid = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// First, query the members of the Alias.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlQueryMembersOfAlias(
|
|||
|
AliasHandle,
|
|||
|
&AliasMemberSids
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto LookupMembersInAliasError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now scan each of the given Member Sids and count it if it is a member
|
|||
|
// of the Alias.
|
|||
|
//
|
|||
|
|
|||
|
for (SidIndex = 0; SidIndex < MemberSids->Count; SidIndex++) {
|
|||
|
|
|||
|
Sid = MemberSids->Sids[ SidIndex].SidPointer;
|
|||
|
|
|||
|
for (AliasMemberSidIndex = 0;
|
|||
|
AliasMemberSidIndex = AliasMemberSids.Count;
|
|||
|
AliasMemberSidIndex++) {
|
|||
|
|
|||
|
AliasMemberSid = AliasMemberSids.Sids[ AliasMemberSidIndex].SidPointer;
|
|||
|
|
|||
|
if (RtlEqualSid( Sid, AliasMemberSid)) {
|
|||
|
|
|||
|
OutputMembershipCount++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*MembershipCount = OutputMembershipCount;
|
|||
|
|
|||
|
LookupMembersInAliasFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
LookupMembersInAliasError:
|
|||
|
|
|||
|
*MembershipCount =0;
|
|||
|
goto LookupMembersInAliasFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlDeleteAlias(
|
|||
|
IN SAMPR_HANDLE *AliasHandle
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function deletes an alias.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AliasHandle - Pointer to Handle to Alias
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
NTSTATUS - Standard Nt Result Code
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
PSAMP_AL_MEMBER_ALIAS_LIST MemberAliasList = NULL;
|
|||
|
PSAMP_AL_MEMBER_DOMAIN MemberDomain = NULL;
|
|||
|
PSAMP_AL_MEMBER_ACCOUNT MemberAccount = NULL;
|
|||
|
BOOLEAN MemberDomainDeleted;
|
|||
|
BOOLEAN MemberAccountDeleted;
|
|||
|
ULONG AliasRid = ((PSAMP_OBJECT) *AliasHandle)->TypeBody.Alias.Rid;
|
|||
|
LONG DomainIndex;
|
|||
|
ULONG RidCount;
|
|||
|
LONG DomainCount;
|
|||
|
ULONG AccountIndex;
|
|||
|
SAMPR_ULONG_ARRAY AliasRids;
|
|||
|
AliasRids.Count = 1;
|
|||
|
AliasRids.Element = &AliasRid;
|
|||
|
|
|||
|
//
|
|||
|
// Obtain pointer to Member Alias List.
|
|||
|
//
|
|||
|
|
|||
|
MemberAliasList = SampAlAliasHandleToMemberAliasList( *AliasHandle );
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto DeleteAliasError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Traverse the Member Alias List. Look in every Member Account for the
|
|||
|
// Alias and remove it if present. This is rather slow if there is a
|
|||
|
// large number of alias relationships for diverse domains.
|
|||
|
//
|
|||
|
DomainCount = (LONG) MemberAliasList->DomainCount;
|
|||
|
for (DomainIndex = 0,
|
|||
|
MemberDomain = SampAlFirstMemberDomain( MemberAliasList );
|
|||
|
DomainIndex < DomainCount;
|
|||
|
DomainIndex++ ) {
|
|||
|
|
|||
|
RidCount = MemberDomain->RidCount;
|
|||
|
for (AccountIndex = 0,
|
|||
|
MemberAccount = SampAlFirstMemberAccount( MemberDomain );
|
|||
|
AccountIndex < RidCount;
|
|||
|
AccountIndex++ ) {
|
|||
|
|
|||
|
ASSERT(MemberAccount->Signature == SAMP_AL_MEMBER_ACCOUNT_SIGNATURE);
|
|||
|
//
|
|||
|
// We now have the MemberAccount. Now remove the Alias from it.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlRemoveAliasesFromMemberAccount(
|
|||
|
&MemberAliasList,
|
|||
|
&MemberDomain,
|
|||
|
&MemberAccount,
|
|||
|
0,
|
|||
|
&AliasRids,
|
|||
|
&MemberDomainDeleted,
|
|||
|
&MemberAccountDeleted
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
if (Status == STATUS_MEMBER_NOT_IN_ALIAS) {
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Move the the next member account unless the one we were pointing
|
|||
|
// to was deleted (in which case the next one moved to us).
|
|||
|
//
|
|||
|
|
|||
|
if (!MemberAccountDeleted) {
|
|||
|
MemberAccount = SampAlNextMemberAccount( MemberAccount );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the member domain was deleted, then the count of members
|
|||
|
// is off as is the member account pointer.
|
|||
|
//
|
|||
|
|
|||
|
if (MemberDomainDeleted) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Move the the next member domain unless the one we were pointing
|
|||
|
// to was deleted (in which case the next one moved to us).
|
|||
|
//
|
|||
|
|
|||
|
if (!MemberDomainDeleted) {
|
|||
|
MemberDomain = SampAlNextMemberDomain( MemberDomain );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto DeleteAliasError;
|
|||
|
}
|
|||
|
|
|||
|
DeleteAliasFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
DeleteAliasError:
|
|||
|
|
|||
|
goto DeleteAliasFinish;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlRemoveAccountFromAllAliases(
|
|||
|
IN PSID AccountSid,
|
|||
|
IN BOOLEAN CheckAccess,
|
|||
|
IN SAMPR_HANDLE DomainHandle OPTIONAL,
|
|||
|
IN PULONG MembershipCount OPTIONAL,
|
|||
|
IN PULONG *Membership OPTIONAL
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine removes the specified account from the member list of all
|
|||
|
aliases in this domain.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AccountSid - The SID of the account being Removed.
|
|||
|
|
|||
|
CheckAccess - if TRUE, this routine will make sure that the caller
|
|||
|
is allowed REMOVE_ALIAS_MEMBER access to this alias. If FALSE,
|
|||
|
the caller is already known to have proper access.
|
|||
|
|
|||
|
DomainHandle - if CheckAccess is TRUE, this handle must be provided
|
|||
|
to allow access to be checked.
|
|||
|
|
|||
|
MembershipCount - if CheckAccess is TRUE, this pointer must be
|
|||
|
provided to receive the number of aliases the account was
|
|||
|
deleted from.
|
|||
|
|
|||
|
Membership - if CheckAccess is TRUE, this pointer must be provided
|
|||
|
to point to a list of aliases the account was removed from. The
|
|||
|
caller must free this list with MIDL_user_free().
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
STATUS_SUCCESS - The user has been Removed from all aliases.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
PSAMP_AL_MEMBER_ALIAS_LIST MemberAliasList = NULL;
|
|||
|
PSAMP_AL_MEMBER_DOMAIN MemberDomain = NULL;
|
|||
|
PSAMP_AL_MEMBER_ACCOUNT MemberAccount = NULL;
|
|||
|
BOOLEAN MemberDomainDeleted;
|
|||
|
PSID DomainSid = NULL;
|
|||
|
LONG DomainIndex;
|
|||
|
ULONG MemberRid, AliasRid;
|
|||
|
SAMPR_ULONG_ARRAY AliasRids;
|
|||
|
AliasRids.Count = 1;
|
|||
|
AliasRids.Element = &AliasRid;
|
|||
|
|
|||
|
//
|
|||
|
// Obtain pointer to Member Alias List for the Current Transaction Domain.
|
|||
|
//
|
|||
|
|
|||
|
DomainIndex = SampTransactionDomainIndex;
|
|||
|
MemberAliasList = SampAlDomainIndexToMemberAliasList( DomainIndex );
|
|||
|
|
|||
|
//
|
|||
|
// We remove the Account from all aliases by locating its Member Account
|
|||
|
// structure and deleting it. First, find the Member Domain.
|
|||
|
//
|
|||
|
|
|||
|
SampSplitSid( AccountSid, &DomainSid, &MemberRid );
|
|||
|
|
|||
|
//
|
|||
|
// Lookup the Member Domain for this DomainSid in the Member Alias
|
|||
|
// List.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlLookupMemberDomain(
|
|||
|
MemberAliasList,
|
|||
|
DomainSid,
|
|||
|
&MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
if (Status != STATUS_NO_SUCH_DOMAIN) {
|
|||
|
|
|||
|
goto RemoveAccountFromAllAliasesError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// There is no member Domain object for this account. This means
|
|||
|
// the account does not belong to any aliases.
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
goto RemoveAccountFromAllAliasesFinish;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We found the Member Domain. Now find the Member Account.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlLookupMemberAccount(
|
|||
|
MemberDomain,
|
|||
|
MemberRid,
|
|||
|
&MemberAccount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
if (Status != STATUS_NO_SUCH_MEMBER) {
|
|||
|
|
|||
|
goto RemoveAccountFromAllAliasesError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
goto RemoveAccountFromAllAliasesFinish;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If CheckAccess = TRUE, return a list of Aliases that the account was
|
|||
|
// a member of.
|
|||
|
//
|
|||
|
|
|||
|
if (CheckAccess) {
|
|||
|
|
|||
|
*Membership = MIDL_user_allocate( MemberAccount->AliasCount * sizeof(ULONG));
|
|||
|
*MembershipCount = MemberAccount->AliasCount;
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
|
|||
|
if (*Membership == NULL) {
|
|||
|
|
|||
|
goto RemoveAccountFromAllAliasesError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We now have the MemberAccount. Now delete it, thereby removing the
|
|||
|
// account from all Aliases.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlDeleteMemberAccount(
|
|||
|
&MemberAliasList,
|
|||
|
&MemberDomain,
|
|||
|
MemberAccount,
|
|||
|
&MemberDomainDeleted
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto RemoveAccountFromAllAliasesError;
|
|||
|
}
|
|||
|
|
|||
|
RemoveAccountFromAllAliasesFinish:
|
|||
|
|
|||
|
//
|
|||
|
// Free the Domain Sid buffer (if any)
|
|||
|
//
|
|||
|
|
|||
|
if (DomainSid != NULL) {
|
|||
|
|
|||
|
MIDL_user_free( DomainSid );
|
|||
|
DomainSid = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
RemoveAccountFromAllAliasesError:
|
|||
|
|
|||
|
if (CheckAccess) {
|
|||
|
|
|||
|
*Membership = NULL;
|
|||
|
*MembershipCount = 0;
|
|||
|
}
|
|||
|
|
|||
|
goto RemoveAccountFromAllAliasesFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlBuildAliasInformation(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function builds the Alias Information for each of the SAM Local
|
|||
|
Domains. For each Domain, this information consists of the Member Alias
|
|||
|
List.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
LONG DomainIndex;
|
|||
|
|
|||
|
for (DomainIndex = 0; DomainIndex < (LONG) SampDefinedDomainsCount; DomainIndex++) {
|
|||
|
|
|||
|
if (SampAlEnableBuildingOfList[ DomainIndex]) {
|
|||
|
|
|||
|
Status = SampAlBuildMemberAliasList( DomainIndex);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto BuildAliasInformationError;
|
|||
|
}
|
|||
|
|
|||
|
BuildAliasInformationFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
BuildAliasInformationError:
|
|||
|
|
|||
|
goto BuildAliasInformationFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Private functions //
|
|||
|
// //
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlCreateMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN ULONG Rid,
|
|||
|
IN ULONG AliasCapacity,
|
|||
|
OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function creates an empty Member Account in the specified Member Domain
|
|||
|
for the specified Member Rid. There must not already be al account for this
|
|||
|
Rid. The Member Account is appended to the end of any existing ones in the
|
|||
|
Member Domain.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to Member Alias List.
|
|||
|
|
|||
|
MemberDomain - Pointer to Member Domain in which the Member Account is
|
|||
|
to be created. The Member Domain must already exist.
|
|||
|
|
|||
|
Rid - Specifies the Account Rid.
|
|||
|
|
|||
|
AliasCapacity - Specifies the initial number of Alias Rids that the
|
|||
|
MemberAccount can hold.
|
|||
|
|
|||
|
MemberAccount - Receives pointer to the newly created Member Account.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG MaximumLengthMemberAccount;
|
|||
|
PSAMP_AL_MEMBER_ACCOUNT OutputMemberAccount = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the length of data needed for the new member Account entry.
|
|||
|
//
|
|||
|
|
|||
|
MaximumLengthMemberAccount = SampAlLengthRequiredMemberAccount( AliasCapacity );
|
|||
|
|
|||
|
//
|
|||
|
// Allocate space for the Member Account.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlAllocateMemberAccount(
|
|||
|
MemberAliasList,
|
|||
|
MemberDomain,
|
|||
|
MaximumLengthMemberAccount,
|
|||
|
&OutputMemberAccount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto CreateMemberAccountError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Scratch the new Member Account
|
|||
|
//
|
|||
|
|
|||
|
OutputMemberAccount->Signature = SAMP_AL_MEMBER_ACCOUNT_SIGNATURE;
|
|||
|
OutputMemberAccount->MaximumLength = MaximumLengthMemberAccount;
|
|||
|
OutputMemberAccount->UsedLength =
|
|||
|
SampAlOffsetFirstAlias( OutputMemberAccount );
|
|||
|
ASSERT(OutputMemberAccount->MaximumLength >=
|
|||
|
OutputMemberAccount->UsedLength);
|
|||
|
OutputMemberAccount->Rid = Rid;
|
|||
|
OutputMemberAccount->AliasCount = 0;
|
|||
|
|
|||
|
((*MemberDomain)->RidCount)++;
|
|||
|
*MemberAccount = OutputMemberAccount;
|
|||
|
|
|||
|
CreateMemberAccountFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
CreateMemberAccountError:
|
|||
|
|
|||
|
*MemberAccount = NULL;
|
|||
|
SampAlInfoMakeInvalid( (*MemberAliasList)->DomainIndex );
|
|||
|
|
|||
|
goto CreateMemberAccountFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlAllocateMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN ULONG MaximumLengthMemberAccount,
|
|||
|
OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function allocates the space for a new Member Account in a Member
|
|||
|
Domain. If necessary, the Mmeber Domain and its associated Member Alias
|
|||
|
List will be grown.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to the Member Alias List.
|
|||
|
|
|||
|
MemberDomain - Pointer to pointer to the Member Domain
|
|||
|
|
|||
|
MaximumLengthMemberAccount - Initial Maximum Length required for the
|
|||
|
Member Account
|
|||
|
|
|||
|
MemberAccount - receives pointer to the newly allocated Member Account
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
ULONG SpaceAvailable;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the space available in the Member Domain
|
|||
|
//
|
|||
|
|
|||
|
SpaceAvailable = (*MemberDomain)->MaximumLength - (*MemberDomain)->UsedLength;
|
|||
|
|
|||
|
if (MaximumLengthMemberAccount > SpaceAvailable) {
|
|||
|
|
|||
|
Status = SampAlGrowMemberDomain(
|
|||
|
MemberAliasList,
|
|||
|
MemberDomain,
|
|||
|
MaximumLengthMemberAccount - SpaceAvailable
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto AllocateMemberAccountError;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The Member Domain is now guaranteed to be large enough. Reserve the
|
|||
|
// space for the new Member Account.
|
|||
|
//
|
|||
|
|
|||
|
*MemberAccount = SampAlNextNewMemberAccount(*MemberDomain);
|
|||
|
(*MemberDomain)->UsedLength += MaximumLengthMemberAccount;
|
|||
|
ASSERT((*MemberDomain)->MaximumLength >=
|
|||
|
(*MemberDomain)->UsedLength);
|
|||
|
|
|||
|
AllocateMemberAccountFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
AllocateMemberAccountError:
|
|||
|
|
|||
|
SampAlInfoMakeInvalid( (*MemberAliasList)->DomainIndex );
|
|||
|
*MemberAccount = NULL;
|
|||
|
|
|||
|
goto AllocateMemberAccountFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlGrowMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount,
|
|||
|
IN ULONG ExtraSpaceRequired
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function grows a Member Account by at least the requested amount. If
|
|||
|
necessary, the containing Member Domain and Member Alias List will also be
|
|||
|
grown.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to the Member Alias List.
|
|||
|
|
|||
|
MemberDomain - Pointer to pointer to the Member Domain
|
|||
|
|
|||
|
MemberAccount - Pointer to Pointer to the Member Account.
|
|||
|
|
|||
|
ExtraSpaceRequired - Extra space needed in the Member Account.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
ULONG SpaceAvailable, MemberAccountOffset, CopyLength;
|
|||
|
PUCHAR Destination = NULL;
|
|||
|
PUCHAR Source = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the space available in the Member Domain
|
|||
|
//
|
|||
|
|
|||
|
SpaceAvailable = (*MemberDomain)->MaximumLength - (*MemberDomain)->UsedLength;
|
|||
|
|
|||
|
if (ExtraSpaceRequired > SpaceAvailable) {
|
|||
|
|
|||
|
//
|
|||
|
// We need to grow the Member Domain. Calculate the offset of the
|
|||
|
// Member Account in the old Member Domain, grow the Member Domain
|
|||
|
// and then calculate the new address of the Member Account.
|
|||
|
//
|
|||
|
|
|||
|
MemberAccountOffset = SampAlMemberAccountToOffset(
|
|||
|
*MemberDomain,
|
|||
|
*MemberAccount
|
|||
|
);
|
|||
|
|
|||
|
Status = SampAlGrowMemberDomain(
|
|||
|
MemberAliasList,
|
|||
|
MemberDomain,
|
|||
|
ExtraSpaceRequired - SpaceAvailable
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto GrowMemberAccountError;
|
|||
|
}
|
|||
|
|
|||
|
*MemberAccount = SampAlMemberAccountFromOffset(
|
|||
|
*MemberDomain,
|
|||
|
MemberAccountOffset
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The Member Domain is now guaranteed to be large enough.
|
|||
|
// Now shift any Member Accounts that follow the one being grown
|
|||
|
// up to make room for the expanded Member Account. The source address
|
|||
|
// for the move is the address of the next Member Account (if any) based
|
|||
|
// on the existing size of the Member Account. The destination address
|
|||
|
// of the move is the address of the next Member Account (if any) based
|
|||
|
// on the new size of the Member Account.
|
|||
|
//
|
|||
|
|
|||
|
Source = (PUCHAR) SampAlNextMemberAccount( *MemberAccount );
|
|||
|
(*MemberAccount)->MaximumLength += ExtraSpaceRequired;
|
|||
|
Destination = (PUCHAR) SampAlNextMemberAccount( *MemberAccount );
|
|||
|
CopyLength =
|
|||
|
(((PUCHAR)(SampAlNextNewMemberAccount(*MemberDomain))) - Source);
|
|||
|
|
|||
|
//
|
|||
|
// Reserve the space in the Member Domain. If all's well, the
|
|||
|
// end of the destination buffer should match the updated end of the
|
|||
|
// used area of the Member Domain.
|
|||
|
//
|
|||
|
|
|||
|
(*MemberDomain)->UsedLength += ExtraSpaceRequired;
|
|||
|
ASSERT((*MemberDomain)->MaximumLength >=
|
|||
|
(*MemberDomain)->UsedLength);
|
|||
|
|
|||
|
ASSERT( Destination + CopyLength ==
|
|||
|
(PUCHAR) SampAlNextNewMemberAccount( *MemberDomain ));
|
|||
|
ASSERT( Destination + CopyLength <=
|
|||
|
(PUCHAR)(*MemberAliasList) + (*MemberAliasList)->MaximumLength );
|
|||
|
ASSERT( Destination + CopyLength <=
|
|||
|
(PUCHAR)(*MemberDomain) + (*MemberDomain)->MaximumLength );
|
|||
|
|
|||
|
if (CopyLength > 0) {
|
|||
|
|
|||
|
RtlMoveMemory( Destination, Source, CopyLength );
|
|||
|
}
|
|||
|
|
|||
|
GrowMemberAccountFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
GrowMemberAccountError:
|
|||
|
|
|||
|
SampAlInfoMakeInvalid( (*MemberAliasList)->DomainIndex );
|
|||
|
|
|||
|
goto GrowMemberAccountFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlLookupMemberAccount(
|
|||
|
IN PSAMP_AL_MEMBER_DOMAIN MemberDomain,
|
|||
|
IN ULONG MemberRid,
|
|||
|
OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function looks up an Account Rid in a Member Domain to see if there
|
|||
|
is a Member Account structure for it.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberDomain - Pointer to Member Domain
|
|||
|
|
|||
|
MemberRid - Specifies the Account Rid
|
|||
|
|
|||
|
MemberAccount - Receives pointer to Member Account if found.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PSAMP_AL_MEMBER_ACCOUNT NextMemberAccount = NULL;
|
|||
|
ULONG RidIndex;
|
|||
|
BOOLEAN AccountFound = FALSE;
|
|||
|
|
|||
|
|
|||
|
for (RidIndex = 0,
|
|||
|
NextMemberAccount = SampAlFirstMemberAccount( MemberDomain );
|
|||
|
RidIndex < MemberDomain->RidCount;
|
|||
|
RidIndex++, NextMemberAccount = SampAlNextMemberAccount( NextMemberAccount)) {
|
|||
|
|
|||
|
if (MemberRid == NextMemberAccount->Rid) {
|
|||
|
|
|||
|
AccountFound = TRUE;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_NO_SUCH_MEMBER;
|
|||
|
|
|||
|
if (!AccountFound) {
|
|||
|
|
|||
|
goto LookupMemberAccountError;
|
|||
|
}
|
|||
|
|
|||
|
*MemberAccount = NextMemberAccount;
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
LookupMemberAccountFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
LookupMemberAccountError:
|
|||
|
|
|||
|
goto LookupMemberAccountFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlAddAliasesToMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount,
|
|||
|
IN ULONG Options,
|
|||
|
IN PSAMPR_ULONG_ARRAY AliasRids
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function adds an array of aliases to a Member Account. An error
|
|||
|
will be returned if any of the aliases exist in the Member Account.
|
|||
|
If necessary, the containing Member Account, Member Domain and Member
|
|||
|
Alias List will also be grown.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to the Member Alias List.
|
|||
|
|
|||
|
MemberDomain - Pointer to pointer to the Member Domain
|
|||
|
|
|||
|
MemberAccount - Pointer to Pointer to the Member Account.
|
|||
|
|
|||
|
Options - Specifies optional actions to be taken
|
|||
|
|
|||
|
SAMP_AL_VERIFY_NO_ALIASES_IN_ACCOUNT - Verify that none of the
|
|||
|
Aliases presented belong to the various Member Accounts.
|
|||
|
|
|||
|
AliasRids - Pointer to counted array of Alias Rids.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
ULONG SpaceRequired, SpaceAvailable, CopyLength;
|
|||
|
PUCHAR Source = NULL;
|
|||
|
PUCHAR Destination = NULL;
|
|||
|
ULONG ExistingAliasCount;
|
|||
|
|
|||
|
//
|
|||
|
// If requested, verify that none of the Aliases are already
|
|||
|
// in the Member Account
|
|||
|
//
|
|||
|
|
|||
|
if (Options & SAMP_AL_VERIFY_NO_ALIASES_IN_ACCOUNT) {
|
|||
|
|
|||
|
Status = SampAlLookupAliasesInMemberAccount(
|
|||
|
*MemberAccount,
|
|||
|
AliasRids,
|
|||
|
&ExistingAliasCount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto AddAliasesToMemberAccountError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_MEMBER_IN_ALIAS;
|
|||
|
|
|||
|
if (ExistingAliasCount > 0) {
|
|||
|
|
|||
|
goto AddAliasesToMemberAccountError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the space required for the new Aliases.
|
|||
|
//
|
|||
|
|
|||
|
SpaceRequired = AliasRids->Count * sizeof( ULONG );
|
|||
|
|
|||
|
//
|
|||
|
// If there is not enough space available in the Member Account,
|
|||
|
// grow it.
|
|||
|
//
|
|||
|
|
|||
|
SpaceAvailable = (*MemberAccount)->MaximumLength - (*MemberAccount)->UsedLength;
|
|||
|
|
|||
|
if (SpaceRequired > SpaceAvailable) {
|
|||
|
|
|||
|
Status = SampAlGrowMemberAccount(
|
|||
|
MemberAliasList,
|
|||
|
MemberDomain,
|
|||
|
MemberAccount,
|
|||
|
SpaceRequired - SpaceAvailable
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto AddAliasesToMemberAccountError;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The Member Account is now large enough. Copy in the aliases.
|
|||
|
//
|
|||
|
|
|||
|
Destination = (PUCHAR) SampAlNextNewAliasInMemberAccount( *MemberAccount );
|
|||
|
Source = (PUCHAR) AliasRids->Element;
|
|||
|
CopyLength = SpaceRequired;
|
|||
|
(*MemberAccount)->UsedLength += SpaceRequired;
|
|||
|
ASSERT((*MemberAccount)->MaximumLength >=
|
|||
|
(*MemberAccount)->UsedLength);
|
|||
|
RtlMoveMemory( Destination, Source, CopyLength );
|
|||
|
|
|||
|
//
|
|||
|
// Update the count of Aliases both in this Member Account and in the
|
|||
|
// Member Alias List.
|
|||
|
//
|
|||
|
|
|||
|
(*MemberAccount)->AliasCount += AliasRids->Count;
|
|||
|
|
|||
|
AddAliasesToMemberAccountFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
AddAliasesToMemberAccountError:
|
|||
|
|
|||
|
goto AddAliasesToMemberAccountFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlLookupAliasesInMemberAccount(
|
|||
|
IN PSAMP_AL_MEMBER_ACCOUNT MemberAccount,
|
|||
|
IN PSAMPR_ULONG_ARRAY AliasRids,
|
|||
|
OUT PULONG ExistingAliasCount
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function checks a set of Alias Rids to see if any are present in a
|
|||
|
Member Account.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAccount - Pointer to Member Account
|
|||
|
|
|||
|
AliasRids - Specifies counted array of Alias Rids.
|
|||
|
|
|||
|
ExistingAliasCount - Receives a count of the Alias Rids presented that
|
|||
|
are already in the Member Account.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
ULONG AliasIndex, AliasInMemberAccountIndex;
|
|||
|
|
|||
|
//
|
|||
|
// Scan the Alias Rids, looking each one up.
|
|||
|
//
|
|||
|
|
|||
|
for (AliasIndex = 0; AliasIndex < AliasRids->Count; AliasRids++ ) {
|
|||
|
|
|||
|
for (AliasInMemberAccountIndex = 0;
|
|||
|
AliasInMemberAccountIndex < MemberAccount->AliasCount;
|
|||
|
AliasInMemberAccountIndex++) {
|
|||
|
|
|||
|
if (AliasRids->Element[ AliasIndex ] ==
|
|||
|
MemberAccount->AliasRids[ AliasInMemberAccountIndex ] ) {
|
|||
|
|
|||
|
(*ExistingAliasCount)++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlRemoveAliasesFromMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN OUT PSAMP_AL_MEMBER_ACCOUNT *MemberAccount,
|
|||
|
IN ULONG Options,
|
|||
|
IN PSAMPR_ULONG_ARRAY AliasRids,
|
|||
|
OUT PBOOLEAN MemberDomainDeleted,
|
|||
|
OUT PBOOLEAN MemberAccountDeleted
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function removes aliases from a Member Account. The Aliases need
|
|||
|
not already exist unless an option to check that they do exist is
|
|||
|
specified. No down sizing of the Member Account occurs, but an
|
|||
|
empty one will be deleted.
|
|||
|
|
|||
|
NOTE: I don't know why ScottBi made MemberAliasList, MemberDomain, and
|
|||
|
MemberAccount parameters pointers to pointers. He never updates
|
|||
|
the pointers so he could have passed them in directly. JK
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to the Member Alias List.
|
|||
|
|
|||
|
MemberDomain - Pointer to pointer to the Member Domain
|
|||
|
|
|||
|
MemberAccount - Pointer to Pointer to the Member Account.
|
|||
|
|
|||
|
Options - Specifies optional actions to be taken
|
|||
|
|
|||
|
SAMP_AL_VERIFY_ALL_ALIASES_IN_ACCOUNT - Verify that none of the
|
|||
|
Aliases presented belong to the Member Account.
|
|||
|
|
|||
|
MemberDomainDeleted - Will be set to TRUE if the member domain
|
|||
|
pointed to by MemberDomain was deleted. Otherwise FALSE is returned.
|
|||
|
|
|||
|
MemberAccountDeleted - Will be set to TRUE if the member account
|
|||
|
pointed to by MemberAccount was deleted. Otherwise FALSE is returned.
|
|||
|
|
|||
|
AliasRids - Pointer to counted array of Alias Rids.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
ULONG ExistingAliasIndex, LastAliasIndex, RemoveAliasIndex, ExistingAlias;
|
|||
|
ULONG ExistingAliasCount;
|
|||
|
|
|||
|
(*MemberDomainDeleted) = FALSE;
|
|||
|
(*MemberAccountDeleted) = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// If requested, verify that all of the Aliases are already
|
|||
|
// in the Member Account
|
|||
|
//
|
|||
|
|
|||
|
if (Options & SAMP_AL_VERIFY_ALL_ALIASES_IN_ACCOUNT) {
|
|||
|
|
|||
|
Status = SampAlLookupAliasesInMemberAccount(
|
|||
|
*MemberAccount,
|
|||
|
AliasRids,
|
|||
|
&ExistingAliasCount
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto RemoveAliasesFromMemberAccountError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_MEMBER_IN_ALIAS;
|
|||
|
|
|||
|
if (ExistingAliasCount < AliasRids->Count) {
|
|||
|
|
|||
|
goto RemoveAliasesFromMemberAccountError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the Member Account is empty, then somebody forgot to delete it
|
|||
|
//
|
|||
|
|
|||
|
ASSERT((*MemberAccount)->AliasCount != 0);
|
|||
|
|
|||
|
|
|||
|
LastAliasIndex = (*MemberAccount)->AliasCount - 1;
|
|||
|
|
|||
|
for (ExistingAliasIndex = 0;
|
|||
|
ExistingAliasIndex < (*MemberAccount)->AliasCount;
|
|||
|
ExistingAliasIndex++) {
|
|||
|
|
|||
|
ExistingAlias = (*MemberAccount)->AliasRids[ ExistingAliasIndex ];
|
|||
|
|
|||
|
for (RemoveAliasIndex = 0;
|
|||
|
RemoveAliasIndex < AliasRids->Count;
|
|||
|
RemoveAliasIndex++) {
|
|||
|
|
|||
|
if (ExistingAlias == AliasRids->Element[ RemoveAliasIndex ]) {
|
|||
|
|
|||
|
//
|
|||
|
// We're to delete this Alias. If this Alias Rid is not at the
|
|||
|
// end of the list contained in the Member Account, overwrite
|
|||
|
// it with the one at the end of the list.
|
|||
|
//
|
|||
|
|
|||
|
if (ExistingAliasIndex < LastAliasIndex) {
|
|||
|
|
|||
|
(*MemberAccount)->AliasRids[ ExistingAliasIndex] =
|
|||
|
(*MemberAccount)->AliasRids[ LastAliasIndex];
|
|||
|
}
|
|||
|
|
|||
|
(*MemberAccount)->AliasCount--;
|
|||
|
(*MemberAccount)->UsedLength -= sizeof(ULONG);
|
|||
|
ASSERT((*MemberAccount)->MaximumLength >=
|
|||
|
(*MemberAccount)->UsedLength);
|
|||
|
|
|||
|
//
|
|||
|
// If the Member Account is now empty, quit.
|
|||
|
//
|
|||
|
|
|||
|
if ((*MemberAccount)->AliasCount == 0) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
LastAliasIndex--;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the Member Account is now empty, quit.
|
|||
|
//
|
|||
|
|
|||
|
if ((*MemberAccount)->AliasCount == 0) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the Member Account is now empty, delete it.
|
|||
|
//
|
|||
|
|
|||
|
if ((*MemberAccount)->AliasCount == 0) {
|
|||
|
|
|||
|
Status = SampAlDeleteMemberAccount(
|
|||
|
MemberAliasList,
|
|||
|
MemberDomain,
|
|||
|
*MemberAccount,
|
|||
|
MemberDomainDeleted
|
|||
|
);
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
(*MemberAccountDeleted) = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
RemoveAliasesFromMemberAccountFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
RemoveAliasesFromMemberAccountError:
|
|||
|
|
|||
|
goto RemoveAliasesFromMemberAccountFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlDeleteMemberAccount(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN OUT PSAMP_AL_MEMBER_ACCOUNT MemberAccount,
|
|||
|
OUT PBOOLEAN MemberDomainDeleted
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function deletes a Member Account. Currently, the containing
|
|||
|
Member Domain and Member Alias List are not shrunk, but the containing
|
|||
|
Member Domain will be deleted if empty.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to the Member Alias List.
|
|||
|
|
|||
|
MemberDomain - Pointer to pointer to the Member Domain
|
|||
|
|
|||
|
MemberAccount - Pointer to the Member Account.
|
|||
|
|
|||
|
MemberDomainDeleted - Will be set to TRUE if the member domain
|
|||
|
pointed to by MemberDomain was deleted. Otherwise FALSE is returned.
|
|||
|
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
PUCHAR Source = NULL;
|
|||
|
PUCHAR Destination = NULL;
|
|||
|
ULONG CopyLength;
|
|||
|
|
|||
|
(*MemberDomainDeleted) = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate pointers for moving the residual portion of the Member
|
|||
|
// Domain down to close the gap left by the extant Member Account.
|
|||
|
// unused space. The start of the residual portion is the end of the
|
|||
|
// Member Account being deleted. The length of the residual portion is
|
|||
|
// the distance from the start to the end of the used portion of the
|
|||
|
// Member Domain.
|
|||
|
//
|
|||
|
|
|||
|
Source = (PUCHAR) SampAlNextMemberAccount( MemberAccount );
|
|||
|
Destination = (PUCHAR) MemberAccount;
|
|||
|
CopyLength = (PUCHAR) SampAlNextNewMemberAccount( *MemberDomain ) - Source;
|
|||
|
|
|||
|
(*MemberDomain)->UsedLength -= MemberAccount->MaximumLength;
|
|||
|
ASSERT((*MemberDomain)->MaximumLength >=
|
|||
|
(*MemberDomain)->UsedLength);
|
|||
|
(*MemberDomain)->RidCount--;
|
|||
|
|
|||
|
if (CopyLength > 0) {
|
|||
|
|
|||
|
RtlMoveMemory( Destination, Source, CopyLength );
|
|||
|
#if DBG
|
|||
|
{
|
|||
|
PSAMP_AL_MEMBER_ACCOUNT Member = (PSAMP_AL_MEMBER_ACCOUNT) Destination;
|
|||
|
ASSERT(Member->Signature == SAMP_AL_MEMBER_ACCOUNT_SIGNATURE);
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the Member Domain now has no Member Accounts, delete it.
|
|||
|
//
|
|||
|
|
|||
|
if ((*MemberDomain)->RidCount == 0) {
|
|||
|
|
|||
|
Status = SampAlDeleteMemberDomain(
|
|||
|
MemberAliasList,
|
|||
|
*MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
goto DeleteMemberAccountError;
|
|||
|
}
|
|||
|
(*MemberDomainDeleted) = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
DeleteMemberAccountFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
DeleteMemberAccountError:
|
|||
|
|
|||
|
goto DeleteMemberAccountFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlCreateMemberDomain(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN PSID DomainSid,
|
|||
|
OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function creates a new Member Domain in the specified Alias Member
|
|||
|
List.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to Alias Member List.
|
|||
|
|
|||
|
DomainSid - Pointer to Sid of Domain to which this MemberDomain
|
|||
|
relates.
|
|||
|
|
|||
|
MemberDomain - Receives pointer to the newly created Member Domain.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PSAMP_AL_MEMBER_DOMAIN OutputMemberDomain = NULL;
|
|||
|
PSAMP_AL_MEMBER_ACCOUNT OutputMemberAccount = NULL;
|
|||
|
ULONG MaximumLengthMemberDomain;
|
|||
|
ULONG DomainSidLength = RtlLengthSid(DomainSid);
|
|||
|
ULONG AlternativeLength;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Allocate the Member Domain.
|
|||
|
//
|
|||
|
|
|||
|
MaximumLengthMemberDomain = SAMP_AL_INITIAL_MEMBER_DOMAIN_LENGTH;
|
|||
|
AlternativeLength = FIELD_OFFSET(SAMP_AL_MEMBER_DOMAIN, DomainSid)
|
|||
|
+ DomainSidLength;
|
|||
|
if (MaximumLengthMemberDomain < AlternativeLength) {
|
|||
|
MaximumLengthMemberDomain = AlternativeLength;
|
|||
|
}
|
|||
|
|
|||
|
Status = SampAlAllocateMemberDomain(
|
|||
|
MemberAliasList,
|
|||
|
MaximumLengthMemberDomain,
|
|||
|
&OutputMemberDomain
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto CreateMemberDomainError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Setup the new Member Domain entry.
|
|||
|
//
|
|||
|
|
|||
|
OutputMemberDomain->MaximumLength = MaximumLengthMemberDomain;
|
|||
|
OutputMemberDomain->RidCount = 0;
|
|||
|
OutputMemberDomain->Signature = SAMP_AL_MEMBER_DOMAIN_SIGNATURE;
|
|||
|
|
|||
|
RtlCopySid(
|
|||
|
DomainSidLength,
|
|||
|
&OutputMemberDomain->DomainSid,
|
|||
|
DomainSid
|
|||
|
);
|
|||
|
|
|||
|
OutputMemberDomain->UsedLength = SampAlOffsetFirstMemberAccount(
|
|||
|
OutputMemberDomain
|
|||
|
);
|
|||
|
ASSERT(OutputMemberDomain->MaximumLength >=
|
|||
|
OutputMemberDomain->UsedLength);
|
|||
|
|
|||
|
((*MemberAliasList)->DomainCount)++;
|
|||
|
*MemberDomain = OutputMemberDomain;
|
|||
|
|
|||
|
CreateMemberDomainFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
CreateMemberDomainError:
|
|||
|
|
|||
|
*MemberDomain = NULL;
|
|||
|
goto CreateMemberDomainFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlAllocateMemberDomain(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN ULONG MaximumLengthMemberDomain,
|
|||
|
OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function allocates the space for a new Member Domain in a Member
|
|||
|
Alias List. If necessary, the Member Alias List will be grown.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to the Member Alias List.
|
|||
|
|
|||
|
MaximumLengthMemberDomain - Initial Maximum Length required for the
|
|||
|
Member Domain
|
|||
|
|
|||
|
MemberDomain - Receives pointer to the Member Domain
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
ULONG SpaceAvailable;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the space available in the Member Alias List
|
|||
|
//
|
|||
|
|
|||
|
SpaceAvailable = (*MemberAliasList)->MaximumLength - (*MemberAliasList)->UsedLength;
|
|||
|
|
|||
|
if (MaximumLengthMemberDomain > SpaceAvailable) {
|
|||
|
|
|||
|
Status = SampAlGrowMemberAliasList(
|
|||
|
MemberAliasList,
|
|||
|
MaximumLengthMemberDomain - SpaceAvailable
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto AllocateMemberDomainError;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The Member Alias List is now guaranteed to be large enough. Reserve the
|
|||
|
// space for the new Member Domain.
|
|||
|
//
|
|||
|
|
|||
|
*MemberDomain = SampAlNextNewMemberDomain(*MemberAliasList);
|
|||
|
(*MemberAliasList)->UsedLength += MaximumLengthMemberDomain;
|
|||
|
ASSERT((*MemberAliasList)->MaximumLength >=
|
|||
|
(*MemberAliasList)->UsedLength);
|
|||
|
|
|||
|
AllocateMemberDomainFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
AllocateMemberDomainError:
|
|||
|
|
|||
|
SampAlInfoMakeInvalid( (*MemberAliasList)->DomainIndex );
|
|||
|
*MemberDomain = NULL;
|
|||
|
goto AllocateMemberDomainFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlGrowMemberDomain(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain,
|
|||
|
IN ULONG ExtraSpaceRequired
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function grows a Member Domain by at least the requested amount. If
|
|||
|
necessary, the Member Alias List will also be grown.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to the Member Alias List.
|
|||
|
|
|||
|
MemberDomain - Pointer to pointer to the Member Domain
|
|||
|
|
|||
|
ExtraSpaceRequired - Extra space needed in the Member Domain.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
ULONG SpaceAvailable, MemberDomainOffset, CopyLength;
|
|||
|
PUCHAR Destination = NULL;
|
|||
|
PUCHAR Source = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the space available in the Member Alias List
|
|||
|
//
|
|||
|
|
|||
|
SpaceAvailable = (*MemberAliasList)->MaximumLength - (*MemberAliasList)->UsedLength;
|
|||
|
|
|||
|
if (ExtraSpaceRequired > SpaceAvailable) {
|
|||
|
|
|||
|
//
|
|||
|
// We need to grow the Member Alias List. Calculate the offset of the
|
|||
|
// Member Domain in the old Member Alias List, grow the Member Alias
|
|||
|
// List and then calculate the new address of the Member Domain.
|
|||
|
//
|
|||
|
|
|||
|
MemberDomainOffset = SampAlMemberDomainToOffset(
|
|||
|
*MemberAliasList,
|
|||
|
*MemberDomain
|
|||
|
);
|
|||
|
|
|||
|
Status = SampAlGrowMemberAliasList(
|
|||
|
MemberAliasList,
|
|||
|
ExtraSpaceRequired - SpaceAvailable
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto GrowMemberDomainError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the new address of the Member Domain
|
|||
|
//
|
|||
|
|
|||
|
*MemberDomain = SampAlMemberDomainFromOffset(
|
|||
|
*MemberAliasList,
|
|||
|
MemberDomainOffset
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The Member Alias List is now guaranteed to be large enough.
|
|||
|
// Now shift any Member Domains that follow the one being grown
|
|||
|
// up to make room for the expanded Member Domain. The source address
|
|||
|
// for the move is the address of the next Member Domain (if any) based
|
|||
|
// on the existing size of the Member Domain. The destination address
|
|||
|
// of the move is the address of the next Member Domain (if any) based
|
|||
|
// on the new size of the Member Domain.
|
|||
|
//
|
|||
|
|
|||
|
Source = (PUCHAR) SampAlNextMemberDomain( *MemberDomain );
|
|||
|
(*MemberDomain)->MaximumLength += ExtraSpaceRequired;
|
|||
|
Destination = (PUCHAR) SampAlNextMemberDomain( *MemberDomain );
|
|||
|
CopyLength =
|
|||
|
(((PUCHAR)(SampAlNextNewMemberDomain(*MemberAliasList))) - Source);
|
|||
|
|
|||
|
//
|
|||
|
// Reserve the space in the Member Alias List. If all's well, the
|
|||
|
// end of the destination buffer should match the updated end of the
|
|||
|
// used area of the member Alias List.
|
|||
|
//
|
|||
|
|
|||
|
(*MemberAliasList)->UsedLength += ExtraSpaceRequired;
|
|||
|
ASSERT((*MemberAliasList)->MaximumLength >=
|
|||
|
(*MemberAliasList)->UsedLength);
|
|||
|
|
|||
|
ASSERT( Destination + CopyLength ==
|
|||
|
(PUCHAR) SampAlNextNewMemberDomain( *MemberAliasList ));
|
|||
|
ASSERT( Destination + CopyLength <=
|
|||
|
(PUCHAR)(*MemberAliasList) + (*MemberAliasList)->MaximumLength );
|
|||
|
|
|||
|
if (CopyLength > 0) {
|
|||
|
|
|||
|
RtlMoveMemory( Destination, Source, CopyLength );
|
|||
|
}
|
|||
|
|
|||
|
GrowMemberDomainFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
GrowMemberDomainError:
|
|||
|
|
|||
|
SampAlInfoMakeInvalid( (*MemberAliasList)->DomainIndex );
|
|||
|
|
|||
|
goto GrowMemberDomainFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlLookupMemberDomain(
|
|||
|
IN PSAMP_AL_MEMBER_ALIAS_LIST MemberAliasList,
|
|||
|
IN PSID DomainSid,
|
|||
|
OUT PSAMP_AL_MEMBER_DOMAIN *MemberDomain
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function looks up a Domain Sid in a Member Alias List to find its
|
|||
|
Member Domain structure (if any).
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to Member Alias List
|
|||
|
|
|||
|
DomainSid - Domain Sid whose Member Domain is to be found.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PSAMP_AL_MEMBER_DOMAIN NextMemberDomain = NULL;
|
|||
|
LONG DomainIndex;
|
|||
|
BOOLEAN DomainFound = FALSE;
|
|||
|
|
|||
|
|
|||
|
for (DomainIndex = 0,
|
|||
|
NextMemberDomain = SampAlFirstMemberDomain( MemberAliasList );
|
|||
|
DomainIndex < (LONG) MemberAliasList->DomainCount;
|
|||
|
DomainIndex++, NextMemberDomain = SampAlNextMemberDomain( NextMemberDomain )
|
|||
|
) {
|
|||
|
|
|||
|
if (RtlEqualSid( DomainSid, &NextMemberDomain->DomainSid)) {
|
|||
|
|
|||
|
DomainFound = TRUE;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_NO_SUCH_DOMAIN;
|
|||
|
|
|||
|
if (!DomainFound) {
|
|||
|
|
|||
|
goto LookupMemberDomainError;
|
|||
|
}
|
|||
|
|
|||
|
*MemberDomain = NextMemberDomain;
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
LookupMemberDomainFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
LookupMemberDomainError:
|
|||
|
|
|||
|
*MemberDomain = NULL;
|
|||
|
goto LookupMemberDomainFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlDeleteMemberDomain(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN OUT PSAMP_AL_MEMBER_DOMAIN MemberDomain
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function deletes a Member Domain. The Member Domain may contain
|
|||
|
zero or more Member Accounts. The containing Member Alias List is shrunk.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to the Member Alias List.
|
|||
|
|
|||
|
MemberDomain - Pointer to the Member Domain
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
PUCHAR Source = NULL;
|
|||
|
PUCHAR Destination = NULL;
|
|||
|
ULONG CopyLength;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate pointers for moving the residual portion of the
|
|||
|
// Member Alias List down to close the gap left by the extant Member
|
|||
|
// Domain. The start of the residual portion is the next Member Domain.
|
|||
|
// The size of the portion is the distance between the start and the
|
|||
|
// used portion of the Member Alias List.
|
|||
|
//
|
|||
|
|
|||
|
Source = (PUCHAR) SampAlNextMemberDomain( MemberDomain );
|
|||
|
Destination = (PUCHAR) MemberDomain;
|
|||
|
CopyLength = ((PUCHAR) SampAlNextNewMemberDomain( *MemberAliasList )) - Source;
|
|||
|
|
|||
|
(*MemberAliasList)->UsedLength -= MemberDomain->MaximumLength;
|
|||
|
ASSERT((*MemberAliasList)->MaximumLength >=
|
|||
|
(*MemberAliasList)->UsedLength);
|
|||
|
(*MemberAliasList)->DomainCount--;
|
|||
|
|
|||
|
if (CopyLength > 0) {
|
|||
|
|
|||
|
RtlMoveMemory( Destination, Source, CopyLength );
|
|||
|
}
|
|||
|
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlCreateMemberAliasList(
|
|||
|
IN LONG DomainIndex,
|
|||
|
IN ULONG InitialMemberAliasListLength,
|
|||
|
OUT OPTIONAL PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function creates an empty Member Alias List for the specified SAM Local
|
|||
|
Domain. The Member Alias List will be marked invalid.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DomainIndex - Specifies the Local SAM Domain
|
|||
|
|
|||
|
InitialMemberAliasListLength - Specifies the initial maximum length of the
|
|||
|
Member Alias List in bytes
|
|||
|
|
|||
|
MemberAliasList - Optional pointer to location in which a pointer to the
|
|||
|
Member Alias List will be returned. Note that the pointer can always
|
|||
|
be retrieved given the DomainIndex.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PSAMP_AL_MEMBER_ALIAS_LIST OutputMemberAliasList = NULL;
|
|||
|
PSAMP_AL_ALIAS_INFORMATION AliasInformation = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate memory for the list.
|
|||
|
//
|
|||
|
|
|||
|
OutputMemberAliasList = MIDL_user_allocate( InitialMemberAliasListLength );
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
|
|||
|
if (OutputMemberAliasList == NULL) {
|
|||
|
|
|||
|
goto CreateMemberAliasListError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// Scratch the List header
|
|||
|
//
|
|||
|
|
|||
|
OutputMemberAliasList->Signature = SAMP_AL_MEMBER_ALIAS_LIST_SIGNATURE;
|
|||
|
OutputMemberAliasList->MaximumLength = InitialMemberAliasListLength;
|
|||
|
OutputMemberAliasList->UsedLength = SampAlOffsetFirstMemberDomain(
|
|||
|
OutputMemberAliasList
|
|||
|
);
|
|||
|
ASSERT(OutputMemberAliasList->MaximumLength >=
|
|||
|
OutputMemberAliasList->UsedLength);
|
|||
|
|
|||
|
OutputMemberAliasList->DomainIndex = DomainIndex;
|
|||
|
OutputMemberAliasList->DomainCount = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Link the Member Alias List to the SAM Local Domain info
|
|||
|
//
|
|||
|
|
|||
|
AliasInformation = &(SampDefinedDomains[ DomainIndex].AliasInformation);
|
|||
|
AliasInformation->MemberAliasList = OutputMemberAliasList;
|
|||
|
|
|||
|
*MemberAliasList = OutputMemberAliasList;
|
|||
|
|
|||
|
CreateMemberAliasListFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
CreateMemberAliasListError:
|
|||
|
|
|||
|
*MemberAliasList = NULL;
|
|||
|
goto CreateMemberAliasListFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlGrowMemberAliasList(
|
|||
|
IN OUT PSAMP_AL_MEMBER_ALIAS_LIST *MemberAliasList,
|
|||
|
IN ULONG ExtraSpaceRequired
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function grows a Member Alias List by at least the requested amount.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MemberAliasList - Pointer to pointer to the Member Alias List.
|
|||
|
|
|||
|
ExtraSpaceRequired - Extra space needed in the Member Alias List.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG NewMaximumLengthMemberAliasList;
|
|||
|
PSAMP_AL_MEMBER_ALIAS_LIST OutputMemberAliasList = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the new size of the Member Alias List needed. Round up to
|
|||
|
// a multiple of the granularity.
|
|||
|
//
|
|||
|
|
|||
|
NewMaximumLengthMemberAliasList = (*MemberAliasList)->MaximumLength +
|
|||
|
ExtraSpaceRequired;
|
|||
|
|
|||
|
NewMaximumLengthMemberAliasList +=
|
|||
|
(SAMP_AL_MEMBER_ALIAS_LIST_DELTA - (ULONG) 1);
|
|||
|
|
|||
|
NewMaximumLengthMemberAliasList &=
|
|||
|
((ULONG)(~(SAMP_AL_MEMBER_ALIAS_LIST_DELTA - (ULONG) 1)));
|
|||
|
|
|||
|
//
|
|||
|
// Allocate memory for the grown Member Alias List.
|
|||
|
//
|
|||
|
|
|||
|
OutputMemberAliasList = MIDL_user_allocate(
|
|||
|
NewMaximumLengthMemberAliasList
|
|||
|
);
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
|
|||
|
if (OutputMemberAliasList == NULL) {
|
|||
|
|
|||
|
goto GrowMemberAliasListError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// Copy the old list to the new list and the the new maximum length.
|
|||
|
// Return pointer to new list.
|
|||
|
//
|
|||
|
|
|||
|
RtlMoveMemory(
|
|||
|
OutputMemberAliasList,
|
|||
|
*MemberAliasList,
|
|||
|
(*MemberAliasList)->UsedLength
|
|||
|
);
|
|||
|
|
|||
|
OutputMemberAliasList->MaximumLength = NewMaximumLengthMemberAliasList;
|
|||
|
ASSERT(OutputMemberAliasList->MaximumLength >=
|
|||
|
OutputMemberAliasList->UsedLength);
|
|||
|
*MemberAliasList = OutputMemberAliasList;
|
|||
|
|
|||
|
GrowMemberAliasListFinish:
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
GrowMemberAliasListError:
|
|||
|
|
|||
|
SampAlInfoMakeInvalid( (*MemberAliasList)->DomainIndex );
|
|||
|
|
|||
|
goto GrowMemberAliasListFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SampAlBuildMemberAliasList(
|
|||
|
IN LONG DomainIndex
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function builds the Member Alias List for the specified SAM Local
|
|||
|
Domain. For each Alias, its list of member Sids is read from backing
|
|||
|
storage and MemberDomain and MemberAccount blocks are created.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DomainIndex - Specifies the SAM Local Domain
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status, EnumerationStatus;
|
|||
|
PSAMP_AL_MEMBER_ALIAS_LIST OutputMemberAliasList = NULL;
|
|||
|
PSAMP_AL_MEMBER_DOMAIN MemberDomain = NULL;
|
|||
|
PSAMP_AL_MEMBER_ACCOUNT MemberAccount = NULL;
|
|||
|
SAMPR_ULONG_ARRAY AliasRids;
|
|||
|
ULONG Rids[1], EnumerationContext, AliasCount, AliasRid;
|
|||
|
ULONG AliasIndex;
|
|||
|
PSAMP_OBJECT AccountContext = NULL;
|
|||
|
PSAMP_OBJECT AliasContext = NULL;
|
|||
|
SAMPR_PSID_ARRAY MemberSids;
|
|||
|
ULONG DomainSidMaximumLength = RtlLengthRequiredSid( 256 );
|
|||
|
PSAMPR_ENUMERATION_BUFFER EnumerationBuffer = NULL;
|
|||
|
PSID DomainSid = NULL;
|
|||
|
PSID MemberSid = NULL;
|
|||
|
|
|||
|
AliasRids.Element = Rids;
|
|||
|
|
|||
|
//
|
|||
|
// Mark the Member Alias List invalid
|
|||
|
//
|
|||
|
|
|||
|
SampAlInfoMakeInvalid( DomainIndex );
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a scratch Domain Sid for splitting Sids. This has length
|
|||
|
// equal to maximum possible Sid length.
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
|
|||
|
DomainSid = MIDL_user_allocate( DomainSidMaximumLength );
|
|||
|
|
|||
|
if (DomainSid == NULL) {
|
|||
|
|
|||
|
goto BuildMemberAliasListError;
|
|||
|
}
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// Create an empty Member Alias List and connect it to the
|
|||
|
// local SAM Domain.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlCreateMemberAliasList(
|
|||
|
DomainIndex,
|
|||
|
SAMP_AL_INITIAL_MEMBER_ALIAS_LIST_LENGTH,
|
|||
|
&OutputMemberAliasList
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto BuildMemberAliasListError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// For each Alias in the SAM local domain, add its members to the
|
|||
|
// Alias List
|
|||
|
//
|
|||
|
|
|||
|
EnumerationContext = 0;
|
|||
|
EnumerationStatus = STATUS_MORE_ENTRIES;
|
|||
|
|
|||
|
//
|
|||
|
// It is currently necessary to set the Transaction Domain before
|
|||
|
// calling SampEnumerateAccountNames even though we're not modifying
|
|||
|
// anything. The is because called routine SampBuildAccountKeyName()
|
|||
|
// uses this information.
|
|||
|
//
|
|||
|
|
|||
|
SampTransactionWithinDomain = FALSE;
|
|||
|
SampSetTransactionDomain( DomainIndex );
|
|||
|
|
|||
|
while (EnumerationStatus == STATUS_MORE_ENTRIES) {
|
|||
|
|
|||
|
Status = SampEnumerateAccountNames(
|
|||
|
SampAliasObjectType,
|
|||
|
&EnumerationContext,
|
|||
|
&EnumerationBuffer,
|
|||
|
SAMP_AL_ENUM_PREFERRED_LENGTH,
|
|||
|
0,
|
|||
|
&AliasCount,
|
|||
|
TRUE
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
EnumerationStatus = Status;
|
|||
|
|
|||
|
for (AliasIndex = 0; AliasIndex < AliasCount; AliasIndex++) {
|
|||
|
|
|||
|
AliasRid = EnumerationBuffer->Buffer[ AliasIndex ].RelativeId;
|
|||
|
|
|||
|
//
|
|||
|
// Create a context for the account.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampCreateAccountContext(
|
|||
|
SampAliasObjectType,
|
|||
|
AliasRid,
|
|||
|
TRUE,
|
|||
|
TRUE,
|
|||
|
&AliasContext
|
|||
|
);
|
|||
|
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
//
|
|||
|
// There is a rather ugly feature of the way the DomainIndex
|
|||
|
// field is used in context handles while initializing. This
|
|||
|
// value is set to the count of SAM Local Domains! So, I am
|
|||
|
// setting it to the DomainIndex for the SAM Local Domain we're
|
|||
|
// initializing, since this AliasContext is used only by me.
|
|||
|
//
|
|||
|
|
|||
|
AliasContext->DomainIndex = DomainIndex;
|
|||
|
|
|||
|
Status = SampAlQueryMembersOfAlias(
|
|||
|
AliasContext,
|
|||
|
&MemberSids
|
|||
|
);
|
|||
|
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
//
|
|||
|
// Add these members to the Alias. No need to verify that
|
|||
|
// they are already present since we're loading the Member Alias
|
|||
|
// List from scratch.
|
|||
|
//
|
|||
|
|
|||
|
Status = SampAlAddMembersToAlias(
|
|||
|
AliasContext,
|
|||
|
0,
|
|||
|
&MemberSids
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
SampDeleteContext( AliasContext );
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Enumerate next set of Aliases
|
|||
|
//
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Dispose of the Enumeration Buffer returned by SampEnumerateAccountNames
|
|||
|
//
|
|||
|
|
|||
|
SamIFree_SAMPR_ENUMERATION_BUFFER( EnumerationBuffer );
|
|||
|
EnumerationBuffer = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
goto BuildMemberAliasListError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Mark the Member Alias List valid
|
|||
|
//
|
|||
|
|
|||
|
SampAlInfoMakeValid( DomainIndex );
|
|||
|
|
|||
|
BuildMemberAliasListFinish:
|
|||
|
|
|||
|
SampTransactionWithinDomain = FALSE;
|
|||
|
return(Status);
|
|||
|
|
|||
|
BuildMemberAliasListError:
|
|||
|
|
|||
|
goto BuildMemberAliasListFinish;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SampAlInfoIsValidForDomain(
|
|||
|
IN SAMPR_HANDLE DomainHandle
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function checks whether Alias Information is valid for a specific
|
|||
|
SAM Local Domain
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DomainHandle - Handle to SAM Local Domain
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
BOOLEAN - TRUE if Alias Information is valid. The Alias Information may
|
|||
|
be used in place of the backing storage to determine Alias membership
|
|||
|
FALSE if the Alias Information is not valid. The Alias Information
|
|||
|
does not exist, or is not reliable.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LONG DomainIndex;
|
|||
|
|
|||
|
//
|
|||
|
// Get the Domain Index for the SAM Local Domain specified by DomainHandle.
|
|||
|
|
|||
|
DomainIndex = ((PSAMP_OBJECT) DomainHandle)->DomainIndex;
|
|||
|
|
|||
|
return(SampAlInfoIsValid( DomainIndex ));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SampAlInfoIsValidForAlias(
|
|||
|
IN SAMPR_HANDLE AliasHandle
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function checks whether Alias Information is valid for a specific
|
|||
|
Alias. The information is valid if it is valid for the SAM Local Domain
|
|||
|
containing the Alias.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AliasHandle - Handle to SAM Alias
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
BOOLEAN - TRUE if Alias Information is valid. The Alias Information may
|
|||
|
be used in place of the backing storage to determine Alias membership
|
|||
|
FALSE if the Alias Information is not valid. The Alias Information
|
|||
|
does not exist, or is not reliable.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LONG DomainIndex;
|
|||
|
|
|||
|
//
|
|||
|
// Get the Domain Index for the SAM Local Domain specified by DomainHandle.
|
|||
|
|
|||
|
DomainIndex = ((PSAMP_OBJECT) AliasHandle)->DomainIndex;
|
|||
|
|
|||
|
return(SampAlInfoIsValid( DomainIndex ));
|
|||
|
}
|