2025-04-27 07:49:33 -04:00

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