1061 lines
29 KiB
C
1061 lines
29 KiB
C
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dbsamtst.c
|
|
|
|
Abstract:
|
|
|
|
LSA Database - SAM Database load testing code
|
|
|
|
When enabled, this code provides a mechanism for stress loading of the
|
|
SAM database with a large number of accounts. The load executes in the
|
|
context of lsass.exe, similar to how it does in replication.
|
|
|
|
Author:
|
|
|
|
Scott Birrell (ScottBi) January 10, 1992
|
|
|
|
Environment:
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include <lsapch2.h>
|
|
#include "dbp.h"
|
|
|
|
|
|
//
|
|
// Uncomment the define LSA_SAM_ACCOUNTS_DOMAIN_TEST to enable the
|
|
// code needed for the ctsamdb test program. Recompile dbsamtst.c,
|
|
// dbpolicy.c. rebuild lsasrv.dll and nmake UMTYPE=console UMTEST=ctsamdb.
|
|
//
|
|
|
|
#ifdef LSA_SAM_ACCOUNTS_DOMAIN_TEST
|
|
|
|
//
|
|
// Global data needed by test
|
|
//
|
|
|
|
//
|
|
// Random Unicode text Buffer (gets updated pseudo-randomly during run)
|
|
//
|
|
|
|
#define LSAP_DB_TEST_TEXT_BUFF_CHAR_LENGTH ((ULONG) 1024)
|
|
|
|
#define LSAP_DB_TEST_TEXT_BUFF_BYTE_LENGTH \
|
|
(LSAP_DB_TEST_TEXT_BUFF_CHAR_LENGTH * sizeof (WCHAR))
|
|
|
|
static PWSTR TextBuffer = L"ABCDEFGHIJKLMNOPQRSTUVWXYZAABBCC"
|
|
L"DDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSS"
|
|
L"TTUUVVWWXXYYZZZYXWVUTSRQPONMLKJI"
|
|
L"HGFEDCBAMEJHCKZXHDKCXJHCKXSKLCJJ"
|
|
L"QKXJHDHNSLCJIFUENSGXCJCVKLSJKSHD"
|
|
L"QXKXJHDGHASOESDGPMSDVJKSDNJCKACJ"
|
|
L"AOJSDVJKJASDHABJKACSBNVAJKAJSKDV"
|
|
L"AJLSBSDJBVAJKLQWDQBVAKLJSCVAKLDD"
|
|
L"OJWQEFBNQGOTQJWDBVBJOQWDBXQPJJPB"
|
|
L"QWERTYUIOPASDFGHJKLZXCVBNMQUFIEJ"
|
|
L"ARWFUITYBNOMVJGBLJHKGJKGKGTJHKHS"
|
|
L"AOPDEBLFPYVQRUCVKJGRKSDBKGKWPOID"
|
|
L"MBCZLADJGFDOYEJHLSDYQWHLSOQLFHBF"
|
|
L"MCNXBZLGHKFDKDHSAQTWYEUTODMKCVJW"
|
|
L"QOPKIJUNYBTYVTCRCXEXECDWZQGGICRT"
|
|
L"ZWRFXCERYHVFYJNGHJNMBGTYVFJNMJJK";
|
|
|
|
//
|
|
// Random Unicode text Buffer backup (used for reset)
|
|
//
|
|
|
|
static PWSTR TextBuffBak = L"ABCDEFGHIJKLMNOPQRSTUVWXYZAABBCC"
|
|
L"DDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSS"
|
|
L"TTUUVVWWXXYYZZZYXWVUTSRQPONMLKJI"
|
|
L"HGFEDCBAMEJHCKZXHDKCXJHCKXSKLCJJ"
|
|
L"QKXJHDHNSLCJIFUENSGXCJCVKLSJKSHD"
|
|
L"QXKXJHDGHASOESDGPMSDVJKSDNJCKACJ"
|
|
L"AOJSDVJKJASDHABJKACSBNVAJKAJSKDV"
|
|
L"AJLSBSDJBVAJKLQWDQBVAKLJSCVAKLDD"
|
|
L"OJWQEFBNQGOTQJWDBVBJOQWDBXQPJJPB"
|
|
L"QWERTYUIOPASDFGHJKLZXCVBNMQUFIEJ"
|
|
L"ARWFUITYBNOMVJGBLJHKGJKGKGTJHKHS"
|
|
L"AOPDEBLFPYVQRUCVKJGRKSDBKGKWPOID"
|
|
L"MBCZLADJGFDOYEJHLSDYQWHLSOQLFHBF"
|
|
L"MCNXBZLGHKFDKDHSAQTWYEUTODMKCVJW"
|
|
L"QOPKIJUNYBTYVTCRCXEXECDWZQGGICRT"
|
|
L"ZWRFXCERYHVFYJNGHJNMBGTYVFJNMJJK";
|
|
|
|
static ULONG Array0Index = 0,
|
|
Array1Index = 0,
|
|
Array2Index = 0,
|
|
Array3Index = 0,
|
|
Array4Index = 0,
|
|
Array5Index = 0;
|
|
|
|
|
|
static ULONG Array0[] = { 0, 44, 88 };
|
|
static ULONG Array1[] = { 87,2,45,48,68};
|
|
static ULONG Array2[] = { 23,1,43,37,4,16,8 };
|
|
static ULONG Array3[] = { 64,5,17,29,18,17,22,56,19,20,6 };
|
|
static ULONG Array4[] = { 7,11,97,88,8,5,24,0,99,51,33,20,80 };
|
|
static ULONG Array5[] = { 53,56,3,27,29,98,35,47,53,92,89,4,66,34,1,99,3 };
|
|
|
|
|
|
NTSTATUS
|
|
LsapDbTestLoadSamAccountsDomain(
|
|
IN PUNICODE_STRING NumberOfAccounts
|
|
);
|
|
|
|
NTSTATUS
|
|
LsapDbTestLoadSamAccountsDomainInitialize(
|
|
IN OUT PUSER_ALL_INFORMATION UserInformation
|
|
);
|
|
|
|
NTSTATUS
|
|
LsapDbTestCreateNextAccountInfo(
|
|
IN OUT PUSER_ALL_INFORMATION UserInformation
|
|
);
|
|
|
|
NTSTATUS
|
|
LsapDbTestGenUnicodeString(
|
|
OUT PUNICODE_STRING OutputString,
|
|
IN ULONG MinimumLength,
|
|
IN ULONG MaximumLength
|
|
);
|
|
|
|
PWSTR
|
|
LsapDbTestGenRandomStringPointer(
|
|
IN ULONG MinLengthToLeaveAtEnd
|
|
);
|
|
|
|
ULONG
|
|
LsapDbTestGenRandomNumber(
|
|
IN ULONG MinimumValue,
|
|
IN ULONG MaximumValue
|
|
);
|
|
|
|
NTSTATUS
|
|
LsapDbTestLoadSamAccountsDomain(
|
|
IN PUNICODE_STRING NumberOfAccounts
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function creates a number of users in the local SAM Accounts Domain,
|
|
or deletes previously created users in the domain.
|
|
|
|
Arguments:
|
|
|
|
AccountCount - Specifies the number of accounts to be created. If a negative
|
|
number is specified, the accounts are deleted.
|
|
|
|
Return Values:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status, EnumerateStatus;
|
|
LONG AccountNumber = 0;
|
|
LONG AccountCount = 0;
|
|
LONG CollisionCount = 0;
|
|
LONG ExistingAccountCount = 0;
|
|
LONG DeletedUserCount = 0;
|
|
ANSI_STRING NumberOfAccountsAnsi;
|
|
PLSAPR_POLICY_ACCOUNT_DOM_INFO PolicyAccountDomainInfo = NULL;
|
|
LSA_TRUST_INFORMATION TrustInformation;
|
|
SAMPR_HANDLE LocalSamServerHandle = NULL;
|
|
USER_ALL_INFORMATION UserInformation;
|
|
SAMPR_HANDLE UserHandle = NULL;
|
|
SAMPR_HANDLE LocalSamDomainHandle = NULL;
|
|
ULONG InitialRelativeId, RelativeId;
|
|
ULONG CountReturned;
|
|
SAM_ENUMERATE_HANDLE EnumerationContext = 0;
|
|
PSAMPR_ENUMERATION_BUFFER RidEnumerationBuffer = NULL;
|
|
ULONG NextAccount;
|
|
ULONG ConflictingAccountRid;
|
|
LARGE_INTEGER StartTime, TimeAfterThis100Users, TimeAfterPrevious100Users;
|
|
LARGE_INTEGER TimeForThis100Users, TimeForThis100UsersInMs, TotalTime, TenThousand;
|
|
|
|
|
|
//
|
|
// Open the local SAM Accounts Domain
|
|
//
|
|
// The Sid and Name of the Account Domain are both configurable, and
|
|
// we need to obtain them from the Policy Object. Now obtain the
|
|
// Account Domain Sid and Name by querying the appropriate
|
|
// Policy Information Class.
|
|
//
|
|
|
|
Status = LsarQueryInformationPolicy(
|
|
LsapPolicyHandle,
|
|
PolicyAccountDomainInformation,
|
|
(PLSAPR_POLICY_INFORMATION *) &PolicyAccountDomainInfo
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
KdPrint(("LsarQueryInformationPolicy failed 0x%lx\n", Status));
|
|
goto TestLoadSamAccountsDomainError;
|
|
}
|
|
|
|
//
|
|
// Set up the Trust Information structure for the Account Domain.
|
|
//
|
|
|
|
TrustInformation.Sid = PolicyAccountDomainInfo->DomainSid;
|
|
|
|
RtlCopyMemory(
|
|
&TrustInformation.Name,
|
|
&PolicyAccountDomainInfo->DomainName,
|
|
sizeof (UNICODE_STRING)
|
|
);
|
|
|
|
//
|
|
// Connect to the Local Sam. The LSA server is a trusted client, so we
|
|
// call the internal version of the SamConnect routine.
|
|
//
|
|
|
|
Status = SamIConnect( NULL, &LocalSamServerHandle, 0, TRUE );
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
KdPrint(("SamIConnect failed 0x%lx\n", Status));
|
|
goto TestLoadSamAccountsDomainError;
|
|
}
|
|
|
|
//
|
|
// Open the Account Domain.
|
|
//
|
|
|
|
Status = SamrOpenDomain(
|
|
LocalSamServerHandle,
|
|
DOMAIN_LOOKUP,
|
|
TrustInformation.Sid,
|
|
&LocalSamDomainHandle
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
KdPrint(("SamrOpenDomain failed 0x%lx\n", Status));
|
|
goto TestLoadSamAccountsDomainError;
|
|
}
|
|
|
|
//
|
|
// Now convert the count of accounts from unicode.
|
|
//
|
|
|
|
Status = RtlUnicodeStringToAnsiString(
|
|
&NumberOfAccountsAnsi,
|
|
NumberOfAccounts,
|
|
TRUE
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
KdPrint(("RtlUnicodeStringToAnsiString failed 0x%lx\n", Status));
|
|
goto TestLoadSamAccountsDomainError;
|
|
}
|
|
|
|
AccountCount = (LONG) atoi(NumberOfAccountsAnsi.Buffer);
|
|
|
|
//
|
|
// Tke initial relative id is used by both the create and delete
|
|
// account branches so initialize it here.
|
|
//
|
|
|
|
InitialRelativeId = (ULONG) 0x00001000L;
|
|
|
|
//
|
|
// If the number of accounts is > 0, add the specified number of
|
|
// accounts to the SAM account domain. If the number of accounts is
|
|
// < 0, delete all accounts from the SAM account s domain.
|
|
//
|
|
|
|
if (AccountCount > 0) {
|
|
|
|
//
|
|
// Initialize the constant fields in the UserInformation structure
|
|
//
|
|
|
|
Status = LsapDbTestLoadSamAccountsDomainInitialize(&UserInformation);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
goto TestLoadSamAccountsDomainError;
|
|
}
|
|
|
|
KdPrint(("Sam Account Database Load Begins\n"));
|
|
|
|
Status = NtQuerySystemTime( &StartTime );
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
TimeAfterPrevious100Users = StartTime;
|
|
|
|
//
|
|
// Conversion factor for converting 100ns ticks to milliseconds
|
|
//
|
|
|
|
TenThousand = RtlConvertUlongToLargeInteger((ULONG) 10000);
|
|
|
|
for( AccountNumber = 0; AccountNumber < AccountCount; AccountNumber++) {
|
|
|
|
//
|
|
// Generate Information for this Account
|
|
//
|
|
|
|
Status = LsapDbTestCreateNextAccountInfo(&UserInformation);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
break;
|
|
}
|
|
|
|
RelativeId = InitialRelativeId + (ULONG) AccountNumber;
|
|
|
|
//
|
|
// Create the account
|
|
//
|
|
|
|
ConflictingAccountRid = (ULONG) 0;
|
|
|
|
Status = SamICreateAccountByRid(
|
|
LocalSamDomainHandle,
|
|
SamObjectUser,
|
|
RelativeId,
|
|
(PRPC_UNICODE_STRING) &UserInformation.UserName,
|
|
USER_ALL_ACCESS,
|
|
&UserHandle,
|
|
&ConflictingAccountRid
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
if ((Status == STATUS_USER_EXISTS) || (Status == STATUS_OBJECT_TYPE_MISMATCH)) {
|
|
|
|
CollisionCount++;
|
|
AccountNumber--;
|
|
if ((CollisionCount%100)==0) {
|
|
KdPrint(("."));
|
|
}
|
|
continue;
|
|
}
|
|
|
|
KdPrint(("SamrCreateAccountByRid failed 0x%lx\n", Status));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If an account already existed with the given Rid and had
|
|
// the same account type and name, it will have been opened.
|
|
// Record the number of occurrences of this.
|
|
//
|
|
|
|
if (ConflictingAccountRid == RelativeId) {
|
|
|
|
ExistingAccountCount++;
|
|
}
|
|
|
|
//
|
|
// Set the information for the account
|
|
//
|
|
|
|
UserInformation.UserId = RelativeId;
|
|
|
|
Status = SamrSetInformationUser(
|
|
UserHandle,
|
|
UserAllInformation,
|
|
(PSAMPR_USER_INFO_BUFFER) &UserInformation
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
KdPrint(("SamrSetInformationUser failed 0x%lx\n", Status));
|
|
break;
|
|
}
|
|
|
|
Status = SamrCloseHandle( &UserHandle );
|
|
|
|
if ((AccountNumber > 0) && ((AccountNumber % 100) == 0)) {
|
|
|
|
Status = NtQuerySystemTime( &TimeAfterThis100Users );
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
break;
|
|
}
|
|
|
|
TimeForThis100Users.QuadPart = TimeAfterThis100Users.QuadPart -
|
|
TimeAfterPrevious100Users.QuadPart;
|
|
|
|
TimeForThis100UsersInMs = TimeForThis100Users.QuadPart /
|
|
TenThousand.QuadPart;
|
|
|
|
TotalTime = TimeAfterThis100Users.QuadPart -
|
|
StartTime.QuadPart;
|
|
|
|
KdPrint(("%d Accounts Created\n", AccountNumber));
|
|
KdPrint(("Last 100 users took %d millisecs to create\n", TimeForThis100UsersInMs.LowPart));
|
|
|
|
if (ExistingAccountCount > 0) {
|
|
|
|
KdPrint(("%d Attempts to create non-conflicting existing users\n\n", ExistingAccountCount));
|
|
}
|
|
|
|
if (CollisionCount > 0) {
|
|
|
|
KdPrint(("%d Creation conflicts with existing users\n", CollisionCount));
|
|
}
|
|
|
|
TimeAfterPrevious100Users = TimeAfterThis100Users;
|
|
}
|
|
}
|
|
|
|
KdPrint(("%d Accounts Created\n", AccountNumber));
|
|
KdPrint(("%d existing accounts opened\n", ExistingAccountCount));
|
|
KdPrint(("%d Rid/Name/Type conflicts with existing accounts\n", CollisionCount));
|
|
KdPrint(("\nSam Account Database Load Ends\n"));
|
|
|
|
} else if (AccountCount < 0) {
|
|
|
|
//
|
|
// Delete the accounts
|
|
//
|
|
|
|
KdPrint(("Deleting user accounts with Rid >= 4096 in the local SAM Accounts Domain\n"));
|
|
|
|
EnumerateStatus = STATUS_MORE_ENTRIES;
|
|
|
|
while(EnumerateStatus == STATUS_MORE_ENTRIES) {
|
|
|
|
RidEnumerationBuffer = NULL;
|
|
|
|
Status = SamrEnumerateUsersInDomain(
|
|
LocalSamDomainHandle,
|
|
&EnumerationContext,
|
|
USER_NORMAL_ACCOUNT,
|
|
(PSAMPR_ENUMERATION_BUFFER *) &RidEnumerationBuffer,
|
|
4096,
|
|
&CountReturned
|
|
);
|
|
|
|
EnumerateStatus = Status;
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
KdPrint(("SamrEnumerateUsersInDomain failed 0x%lx\n", Status));
|
|
break;
|
|
}
|
|
|
|
if (CountReturned == 0) {
|
|
|
|
break;
|
|
}
|
|
|
|
for (NextAccount = 0; NextAccount < CountReturned; NextAccount++) {
|
|
|
|
RelativeId = RidEnumerationBuffer->Buffer[ NextAccount ].RelativeId;
|
|
|
|
//
|
|
// Skip this account if it's not one of ours. This is not
|
|
// a rigorous check, but works.
|
|
//
|
|
|
|
if (RelativeId < InitialRelativeId) {
|
|
|
|
continue;
|
|
}
|
|
|
|
Status = SamrOpenUser(
|
|
LocalSamDomainHandle,
|
|
DELETE,
|
|
RelativeId,
|
|
&UserHandle
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
KdPrint(("SamrOpenUser failed 0x%lx\n", Status));
|
|
break;
|
|
}
|
|
|
|
Status = SamrDeleteUser( &UserHandle );
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
if (Status != STATUS_SPECIAL_ACCOUNT) {
|
|
|
|
KdPrint(("SamrDeleteUser failed 0x%lx\n", Status));
|
|
break;
|
|
}
|
|
|
|
Status = SamrCloseHandle(&UserHandle);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
KdPrint(("SamrCloseHandle failed 0x%lx\n", Status));
|
|
break;
|
|
}
|
|
}
|
|
|
|
DeletedUserCount++;
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
KdPrint(("%d user accounts deleted\n", DeletedUserCount));
|
|
KdPrint(("Deletion of user accounts ends\n"));
|
|
}
|
|
}
|
|
|
|
TestLoadSamAccountsDomainFinish:
|
|
|
|
return(Status);
|
|
|
|
TestLoadSamAccountsDomainError:
|
|
|
|
goto TestLoadSamAccountsDomainFinish;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapDbTestLoadSamAccountsDomainInitialize(
|
|
IN OUT PUSER_ALL_INFORMATION UserInformation
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes the constant values required by the
|
|
SAM Accounts Domain load/update tests. These values include
|
|
static global data and fixed values within a USER_ALL_INFORMATION
|
|
structure used for creating/updating accounts.
|
|
|
|
Arguments:
|
|
|
|
UserInformation - Points to USER_ALL_INFORMATION structure.
|
|
|
|
Return Values:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG Index;
|
|
|
|
static UCHAR LogonHours[SAM_HOURS_PER_WEEK / 8];
|
|
|
|
//
|
|
// Restore the Unicode Text Buffer used for generating random
|
|
// Unicode Strings to its original contents.
|
|
//
|
|
|
|
RtlCopyMemory( TextBuffer, TextBuffBak, LSAP_DB_TEST_TEXT_BUFF_CHAR_LENGTH );
|
|
|
|
//
|
|
// Reset the random number generator indices
|
|
//
|
|
|
|
Array0Index = 0;
|
|
Array1Index = 0;
|
|
Array2Index = 0;
|
|
Array3Index = 0;
|
|
Array4Index = 0;
|
|
Array5Index = 0;
|
|
|
|
//
|
|
// Initialize Logon Hours data
|
|
//
|
|
|
|
for( Index = 0; Index < (SAM_HOURS_PER_WEEK / 8); Index++) {
|
|
|
|
LogonHours[Index] = (UCHAR) 0xff;
|
|
}
|
|
|
|
//
|
|
// Initialize constaint values in User Information structure
|
|
//
|
|
|
|
UserInformation->LogonCount = 0;
|
|
UserInformation->LogonHours.UnitsPerWeek = SAM_HOURS_PER_WEEK;
|
|
UserInformation->LogonHours.LogonHours = LogonHours;
|
|
UserInformation->BadPasswordCount = 1;
|
|
UserInformation->LogonCount = 1;
|
|
UserInformation->UserAccountControl = USER_NORMAL_ACCOUNT;
|
|
UserInformation->CountryCode = 1;
|
|
UserInformation->CodePage = 850;
|
|
UserInformation->NtPasswordPresent = FALSE;
|
|
UserInformation->LmPasswordPresent = FALSE;
|
|
UserInformation->PasswordExpired = FALSE;
|
|
UserInformation->SecurityDescriptor.SecurityDescriptor = NULL;
|
|
UserInformation->SecurityDescriptor.Length = 0;
|
|
UserInformation->WhichFields =
|
|
(
|
|
USER_ALL_USERNAME |
|
|
USER_ALL_FULLNAME |
|
|
USER_ALL_ADMINCOMMENT |
|
|
USER_ALL_USERCOMMENT |
|
|
USER_ALL_HOMEDIRECTORY |
|
|
USER_ALL_HOMEDIRECTORYDRIVE |
|
|
USER_ALL_SCRIPTPATH |
|
|
USER_ALL_PROFILEPATH |
|
|
USER_ALL_LOGONHOURS |
|
|
USER_ALL_USERACCOUNTCONTROL
|
|
);
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapDbTestCreateNextAccountInfo(
|
|
IN OUT PUSER_ALL_INFORMATION UserInformation
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function generates the user information for the next user.
|
|
|
|
Arguments:
|
|
|
|
UserInformation - Pointer to User Information structure
|
|
|
|
Return Values:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
#define LSAP_TEST_MIN_USERNAME_LENGTH ((ULONG) 0x00000005L)
|
|
#define LSAP_TEST_MAX_USERNAME_LENGTH ((ULONG) 0x0000000cL)
|
|
|
|
#define LSAP_TEST_MIN_FULLNAME_LENGTH ((ULONG) 0x00000003L)
|
|
#define LSAP_TEST_MAX_FULLNAME_LENGTH ((ULONG) 0x00000030L)
|
|
|
|
#define LSAP_TEST_MIN_HOMEDIR_LENGTH ((ULONG) 0x00000003L)
|
|
#define LSAP_TEST_MAX_HOMEDIR_LENGTH ((ULONG) 0x00000030L)
|
|
|
|
#define LSAP_TEST_MIN_SCRIPTPATH_LENGTH ((ULONG) 0x00000003L)
|
|
#define LSAP_TEST_MAX_SCRIPTPATH_LENGTH ((ULONG) 0x00000100L)
|
|
|
|
#define LSAP_TEST_MIN_PROFPATH_LENGTH ((ULONG) 0x00000003L)
|
|
#define LSAP_TEST_MAX_PROFPATH_LENGTH ((ULONG) 0x00000100L)
|
|
|
|
#define LSAP_TEST_MIN_DRIVE_LENGTH ((ULONG) 0x00000001L)
|
|
#define LSAP_TEST_MAX_DRIVE_LENGTH ((ULONG) 0x00000001L)
|
|
|
|
#define LSAP_TEST_MIN_ADMCMT_LENGTH ((ULONG) 0x00000003L)
|
|
#define LSAP_TEST_MAX_ADMCMT_LENGTH ((ULONG) 0x00000100L)
|
|
|
|
#define LSAP_TEST_MIN_WKSTA_LENGTH ((ULONG) 0x00000003L)
|
|
#define LSAP_TEST_MAX_WKSTA_LENGTH ((ULONG) 0x00000040L)
|
|
|
|
#define LSAP_TEST_MIN_USER_COMMENT_LENGTH ((ULONG) 0x00000003L)
|
|
#define LSAP_TEST_MAX_USER_COMMENT_LENGTH ((ULONG) 0x00000040L)
|
|
|
|
#define LSAP_TEST_MIN_PARAMS_LENGTH ((ULONG) 0x00000003L)
|
|
#define LSAP_TEST_MAX_PARAMS_LENGTH ((ULONG) 0x00000040L)
|
|
|
|
#define LSAP_TEST_MIN_PRIVDATA_LENGTH ((ULONG) 0x00000003L)
|
|
#define LSAP_TEST_MAX_PRIVDATA_LENGTH ((ULONG) 0x00000040L)
|
|
|
|
NTSTATUS Status;
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
&UserInformation->UserName,
|
|
LSAP_TEST_MIN_USERNAME_LENGTH,
|
|
LSAP_TEST_MAX_USERNAME_LENGTH
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
&UserInformation->FullName,
|
|
LSAP_TEST_MIN_FULLNAME_LENGTH,
|
|
LSAP_TEST_MAX_FULLNAME_LENGTH
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
&UserInformation->HomeDirectoryDrive,
|
|
LSAP_TEST_MIN_DRIVE_LENGTH,
|
|
LSAP_TEST_MAX_DRIVE_LENGTH
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
&UserInformation->HomeDirectory,
|
|
LSAP_TEST_MIN_HOMEDIR_LENGTH,
|
|
LSAP_TEST_MAX_HOMEDIR_LENGTH
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
&UserInformation->ScriptPath,
|
|
LSAP_TEST_MIN_SCRIPTPATH_LENGTH,
|
|
LSAP_TEST_MAX_SCRIPTPATH_LENGTH
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
&UserInformation->ProfilePath,
|
|
LSAP_TEST_MIN_PROFPATH_LENGTH,
|
|
LSAP_TEST_MAX_PROFPATH_LENGTH
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
&UserInformation->AdminComment,
|
|
LSAP_TEST_MIN_ADMCMT_LENGTH,
|
|
LSAP_TEST_MAX_ADMCMT_LENGTH
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
&UserInformation->WorkStations,
|
|
LSAP_TEST_MIN_WKSTA_LENGTH,
|
|
LSAP_TEST_MAX_WKSTA_LENGTH
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
&UserInformation->UserComment,
|
|
LSAP_TEST_MIN_USER_COMMENT_LENGTH,
|
|
LSAP_TEST_MAX_USER_COMMENT_LENGTH
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
&UserInformation->Parameters,
|
|
LSAP_TEST_MIN_PARAMS_LENGTH,
|
|
LSAP_TEST_MAX_PARAMS_LENGTH
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return(Status);
|
|
}
|
|
|
|
Status = LsapDbTestGenUnicodeString(
|
|
(PUNICODE_STRING) &UserInformation->PrivateData,
|
|
LSAP_TEST_MIN_PRIVDATA_LENGTH,
|
|
LSAP_TEST_MAX_PRIVDATA_LENGTH
|
|
);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
LsapDbTestGenUnicodeString(
|
|
OUT PUNICODE_STRING OutputString,
|
|
IN ULONG MinimumLength,
|
|
IN ULONG MaximumLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function generates a pseudo-random Unicode String whose length
|
|
lies within the indicated bounds.
|
|
|
|
Arguments:
|
|
|
|
OutputString - Points to output UNICODE_STRING structure to be
|
|
initialized.
|
|
|
|
MinimumLength - Minimum length required in wide characters.
|
|
|
|
MaximumLength - Maximum length required in wide characters.
|
|
|
|
Return Values:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
OutputString->Length = (USHORT) (sizeof(WCHAR) * LsapDbTestGenRandomNumber(
|
|
MinimumLength,
|
|
MaximumLength
|
|
));
|
|
|
|
OutputString->Buffer = LsapDbTestGenRandomStringPointer(
|
|
(OutputString->Length / 2)
|
|
);
|
|
|
|
OutputString->MaximumLength = OutputString->Length;
|
|
|
|
return(Status);
|
|
}
|
|
|
|
PWSTR
|
|
LsapDbTestGenRandomStringPointer(
|
|
IN ULONG MinLengthToLeaveAtEnd
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns a random pointer to a location within a global
|
|
block of text.
|
|
|
|
Arguments:
|
|
|
|
MinLengthToLeaveAtEnd - Specifies the minimum length of the string
|
|
in Wide Chars from the returned pointer to the end of the global buffer.
|
|
|
|
Return Values:
|
|
|
|
PUCHAR - Receives a pointer referencing a character within the block
|
|
of text.
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR Temp;
|
|
|
|
ULONG Offset = LsapDbTestGenRandomNumber(
|
|
0,
|
|
(ULONG) 512 - MinLengthToLeaveAtEnd
|
|
);
|
|
|
|
ULONG Offset1 = LsapDbTestGenRandomNumber(
|
|
0,
|
|
(ULONG) 512 - 1
|
|
);
|
|
|
|
ULONG Offset2 = LsapDbTestGenRandomNumber(
|
|
0,
|
|
(ULONG) 512 - 1
|
|
);
|
|
|
|
ULONG Offset3 = LsapDbTestGenRandomNumber(
|
|
0,
|
|
(ULONG) 512 - 1
|
|
);
|
|
|
|
ULONG Offset4 = LsapDbTestGenRandomNumber(
|
|
0,
|
|
(ULONG) 512 - 1
|
|
);
|
|
|
|
//
|
|
// Randomly alter the 2nd to 6th characters of the selected string.
|
|
//
|
|
|
|
Temp = TextBuffer[Offset + 1];
|
|
TextBuffer[Offset + 1] = TextBuffer[Offset1];
|
|
TextBuffer[Offset1] = Temp;
|
|
|
|
if ((Offset > 0) && (Offset < (ULONG) (512 - 2))) {
|
|
|
|
Temp = TextBuffer[Offset + 2];
|
|
TextBuffer[Offset + 2] = TextBuffer[Offset2];
|
|
TextBuffer[Offset2] = Temp;
|
|
}
|
|
|
|
if ((Offset > 0) && (Offset < (ULONG) (512 - 3))) {
|
|
|
|
Temp = TextBuffer[Offset + 3];
|
|
TextBuffer[Offset + 3] = TextBuffer[Offset3];
|
|
TextBuffer[Offset3] = Temp;
|
|
}
|
|
|
|
if ((Offset > 0) && (Offset < (ULONG) (512 - 4))) {
|
|
|
|
Temp = TextBuffer[Offset + 4];
|
|
TextBuffer[Offset + 4] = TextBuffer[Offset4];
|
|
TextBuffer[Offset4] = Temp;
|
|
}
|
|
|
|
return(&TextBuffer[Offset]);
|
|
}
|
|
|
|
|
|
ULONG
|
|
LsapDbTestGenRandomNumber(
|
|
IN ULONG MinimumValue,
|
|
IN ULONG MaximumValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function generates a pseudo-random unsigned integer lying between
|
|
two values.
|
|
|
|
Arguments:
|
|
|
|
MinimumValue - The minimum value of the random number
|
|
|
|
MaximumValue - The maximum value of the random number
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG NextValue, NextValue1, NextValue2;
|
|
ULONG MaxPossValue = 88 + 87 + 43 + 64 + 99 + 99;
|
|
|
|
Array0Index++;
|
|
if (Array0Index == sizeof(Array0) / sizeof(ULONG)) {
|
|
|
|
Array0Index = 0;
|
|
}
|
|
|
|
Array1Index++;
|
|
if (Array1Index == sizeof(Array1) / sizeof(ULONG)) {
|
|
|
|
Array1Index = 0;
|
|
}
|
|
|
|
Array2Index++;
|
|
if (Array2Index == sizeof(Array2) / sizeof(ULONG)) {
|
|
|
|
Array2Index = 0;
|
|
}
|
|
|
|
Array3Index++;
|
|
if (Array3Index == sizeof(Array3) / sizeof(ULONG)) {
|
|
|
|
Array3Index = 0;
|
|
}
|
|
|
|
Array4Index++;
|
|
if (Array4Index == sizeof(Array4) / sizeof(ULONG)) {
|
|
|
|
Array4Index = 0;
|
|
}
|
|
|
|
Array5Index++;
|
|
if (Array5Index == sizeof(Array5) / sizeof(ULONG)) {
|
|
|
|
Array5Index = 0;
|
|
}
|
|
|
|
NextValue1 = Array0[Array0Index] +
|
|
Array1[Array1Index] +
|
|
Array2[Array2Index] +
|
|
Array3[Array3Index] +
|
|
Array4[Array4Index] +
|
|
Array5[Array5Index];
|
|
|
|
Array0Index++;
|
|
if (Array0Index == sizeof(Array0) / sizeof(ULONG)) {
|
|
|
|
Array0Index = 0;
|
|
}
|
|
|
|
Array1Index++;
|
|
if (Array1Index == sizeof(Array1) / sizeof(ULONG)) {
|
|
|
|
Array1Index = 0;
|
|
}
|
|
|
|
Array2Index++;
|
|
if (Array2Index == sizeof(Array2) / sizeof(ULONG)) {
|
|
|
|
Array2Index = 0;
|
|
}
|
|
|
|
Array3Index++;
|
|
if (Array3Index == sizeof(Array3) / sizeof(ULONG)) {
|
|
|
|
Array3Index = 0;
|
|
}
|
|
|
|
Array4Index++;
|
|
if (Array4Index == sizeof(Array4) / sizeof(ULONG)) {
|
|
|
|
Array4Index = 0;
|
|
}
|
|
|
|
Array5Index++;
|
|
if (Array5Index == sizeof(Array5) / sizeof(ULONG)) {
|
|
|
|
Array5Index = 0;
|
|
}
|
|
|
|
NextValue2 = Array0[Array0Index] +
|
|
Array1[Array1Index] +
|
|
Array2[Array2Index] +
|
|
Array3[Array3Index] +
|
|
Array4[Array4Index] +
|
|
Array5[Array5Index];
|
|
|
|
if (NextValue2 > NextValue1) {
|
|
|
|
NextValue = NextValue2 - NextValue1;
|
|
|
|
} else {
|
|
|
|
NextValue = NextValue1 - NextValue2;
|
|
}
|
|
|
|
NextValue = MinimumValue +
|
|
(MaximumValue - MinimumValue) * NextValue / MaxPossValue;
|
|
|
|
return(NextValue);
|
|
}
|
|
|
|
#endif // LSA_SAM_ACCOUNTS_DOMAIN_TEST
|