/*++ Copyright (c) 1991 Microsoft Corporation Module Name: dbinstal.c Abstract: LSA Protected Subsystem - Database Installation. This module contains code which will create an initial LSA Database if none exists. Temporarily, this code is executed from within LSA Initialization. This code will form part of the Security Installation applet when implemented. WARNING! THE CODE IN THIS MODULE IS TEMPORARY. IT WILL BE REPLACED BY SYSTEM INSTALLATION FUNCTIONALITY. Author: Scott Birrell (ScottBi) August 2, 1991 Environment: User mode - Does not depend on Windows. Revision History: --*/ #include #include "dbp.h" VOID LsapDbSetDomainInfo( IN PLSAP_DB_ATTRIBUTE *NextAttribute, IN ULONG *AttributeCount ); NTSTATUS LsapDbGetNextValueToken( IN PUNICODE_STRING Value, IN OUT PULONG ParseContext, OUT PUNICODE_STRING *ReturnString ); NTSTATUS LsapDbInstallLsaDatabase( ULONG Pass ) /*++ Routine Description: This function installs an initial LSA Database. Any existing database will be reset to have its initial attributes. Arguments: Pass - Either 1 or 2. During pass 1 all information that is not product type-specific is initialized. In pass 2, the product type-specific stuff is initialized. Return Value: NTSTATUS - Standard Nt Result Code --*/ { NTSTATUS Status; // // Install the LSA Database Policy Object. // Status = LsapDbInstallPolicyObject(Pass); return(Status); } NTSTATUS LsapDbInstallPolicyObject( IN ULONG Pass ) /*++ Routine Description: This function installs the LSA Database Policy Object, setting its attributes to the default state. It is called as part of the LSA Database Installation Procedure. Arguments: Pass - Either 1 or 2. During pass 1 all information that is not product type-specific is initialized. In pass 2, the product type-specific stuff is initialized. Return Value: --*/ { NTSTATUS Status = STATUS_SUCCESS; LSAP_DB_OBJECT_INFORMATION ObjectInformation; LSAP_DB_HANDLE Handle; POLICY_LSA_SERVER_ROLE ServerRole; LSAP_DB_POLICY_PRIVATE_DATA PolicyPrivateData; LSARM_POLICY_AUDIT_EVENTS_INFO InitialAuditEventInformation; POLICY_AUDIT_LOG_INFO InitialAuditLogInformation; LSAP_DB_ATTRIBUTE Attributes[21]; PLSAP_DB_ATTRIBUTE NextAttribute; ULONG AttributeCount = 0; BOOLEAN ObjectReferenced = FALSE; ULONG Revision; LSAP_DB_ENCRYPTION_KEY NewEncryptionKey; ULONG SyskeyLength; PVOID Syskey; QUOTA_LIMITS InstalledQuotaLimits; NextAttribute = Attributes; LsapDiagPrint( DB_INIT, ("LSA (init): Performing pass %d of LSA Policy Initialization\n", Pass ) ); if (Pass == 1) { // // Set up the Object Information for creating the Policy Object. // Note that we put NULL for Security Quality Of Service since this // open does not involve impersonation. // ObjectInformation.ObjectTypeId = PolicyObject; ObjectInformation.Sid = NULL; ObjectInformation.ObjectAttributeNameOnly = FALSE; InitializeObjectAttributes( &ObjectInformation.ObjectAttributes, &LsapDbNames[Policy], 0L, NULL, NULL ); Handle = LsapDbHandle; // // Create the revision attribute // Revision = LSAP_DB_REVISION_1_7; LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[PolRevision], &Revision, sizeof (ULONG), FALSE ); NextAttribute++; AttributeCount++; // // Install initial Private Data. For now, just one ULONG is stored. // PolicyPrivateData.NoneDefinedYet = 0; LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[PolState], &PolicyPrivateData, sizeof (LSAP_DB_POLICY_PRIVATE_DATA), FALSE ); NextAttribute++; AttributeCount++; // // Initialize the Policy Modification Info. Set the Modification // Id to 1 and set the Database Creation Time to the current time. // LsapDbState.PolicyModificationInfo.ModifiedId = RtlConvertUlongToLargeInteger( (ULONG) 1 ); Status = NtQuerySystemTime( &LsapDbState.PolicyModificationInfo.DatabaseCreationTime ); if (!NT_SUCCESS(Status)) { goto InstallPolicyObjectError; } LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[PolMod], &LsapDbState.PolicyModificationInfo, sizeof (POLICY_MODIFICATION_INFO), FALSE ); NextAttribute++; AttributeCount++; // // Initialize Default Event Auditing Options. No auditing is specified // for any event type. These will be set in the Policy Database later // when the Policy Object is created. // Status = LsapAdtInitializeDefaultAuditing( (ULONG) 0, &InitialAuditEventInformation ); LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[PolAdtEv], &InitialAuditEventInformation, sizeof (LSARM_POLICY_AUDIT_EVENTS_INFO), FALSE ); NextAttribute++; AttributeCount++; // // Create the Containing Directory "Accounts" for the user and group // accounts objects. // LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[Accounts], NULL, 0L, FALSE ); NextAttribute++; AttributeCount++; // // Create the Containing Directory "Domains" for the Trusted Domain // objects. // LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[Domains], NULL, 0L, FALSE ); NextAttribute++; AttributeCount++; // // Create the Containing Directory "Secrets" for the Secret objects. // LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[Secrets], NULL, 0L, FALSE ); // // Create the Lsa Database Policy Object, opening the existing one if // it exists. // NextAttribute++; AttributeCount++; ////////////////////////////////////////////////// // // // ATTRIBUTES BELOW THIS POINT ARE INITIALIZED // // IN PASS 1, BUT MAY BE CHANGED IN PASS 2. // // IN GENERAL, THINGS ARE SET FOR A WIN-NT PROD // // AND CHANGED IN PASS 2 IF NECESSARY. // // // ////////////////////////////////////////////////// // // Initialize the default installed quota limit values // ALL THIS QUOTA STUFF SHOULD REALLY BE PULLED - it's not used for anything // #define LSAP_DB_WINNT_PAGED_POOL (0x02000000L) #define LSAP_DB_WINNT_NON_PAGED_POOL (0x00100000L) #define LSAP_DB_WINNT_MIN_WORKING_SET (0x00010000L) #define LSAP_DB_WINNT_MAX_WORKING_SET (0x0f000000L) #define LSAP_DB_WINNT_PAGEFILE (0x0f000000L) InstalledQuotaLimits.PagedPoolLimit = LSAP_DB_WINNT_PAGED_POOL; InstalledQuotaLimits.NonPagedPoolLimit = LSAP_DB_WINNT_NON_PAGED_POOL; InstalledQuotaLimits.MinimumWorkingSetSize = LSAP_DB_WINNT_MIN_WORKING_SET; InstalledQuotaLimits.MaximumWorkingSetSize = LSAP_DB_WINNT_MAX_WORKING_SET; LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[DefQuota], &InstalledQuotaLimits, sizeof (QUOTA_LIMITS), FALSE ); NextAttribute++; AttributeCount++; // // Initialize the audit log information. // InitialAuditLogInformation.MaximumLogSize = 8*1024; InitialAuditLogInformation.AuditLogPercentFull = 0; InitialAuditLogInformation.AuditRetentionPeriod.LowPart = 0x823543; InitialAuditLogInformation.AuditRetentionPeriod.HighPart = 0; InitialAuditLogInformation.AuditLogFullShutdownInProgress = FALSE; InitialAuditLogInformation.TimeToShutdown.LowPart = 0x46656; InitialAuditLogInformation.TimeToShutdown.HighPart = 0; LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[PolAdtLg], &InitialAuditLogInformation, sizeof (POLICY_AUDIT_LOG_INFO), FALSE ); NextAttribute++; AttributeCount++; // // Initialize the syskey // Status = LsapDbSetupInitialSyskey( &SyskeyLength, &Syskey ); if (!NT_SUCCESS(Status)) { LsapLogError( "LsapDbInstallPolicyObject: Syskey setup failed 0x%lx\n", Status ); goto InstallPolicyObjectError; } // // Initialize the key for secret encryption // Status = LsapDbGenerateNewKey( &NewEncryptionKey ); if (!NT_SUCCESS(Status)) { LsapLogError( "LsapDbInstallPolicyObject: New key generation failed 0x%lx\n", Status ); goto InstallPolicyObjectError; } // // Encrypt the key with syskey // LsapDbEncryptKeyWithSyskey( &NewEncryptionKey, Syskey, SyskeyLength ); // // Set the global variable LsapDbSyskey to reflect this value // LsapDbSysKey = Syskey; // // Add the attribute for the list of attributes to be added to the database. // LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[PolSecretEncryptionKey], &NewEncryptionKey, sizeof (NewEncryptionKey), FALSE ); NextAttribute++; AttributeCount++; Status = LsapDbCreateObject( &ObjectInformation, GENERIC_ALL, LSAP_DB_OBJECT_OPEN_IF, LSAP_DB_TRUSTED, Attributes, &AttributeCount, RTL_NUMBER_OF(Attributes), &LsapDbHandle ); if (!NT_SUCCESS(Status)) { LsapLogError( "LsapDbInstallPolicyObject: Create Policy object failed 0x%lx\n", Status ); LsapDiagPrint( DB_INIT, ("LSA (init): Attributes passed to CreateObject call:\n\n" " Count: %d\n" " Array Address: 0x%lx", AttributeCount, Attributes) ); ASSERT(NT_SUCCESS(Status)); // Provide a debug opportunity goto InstallPolicyObjectError; } } else if (Pass == 2) { // // Set up the account objects necessary to implement the default // Microsoft Policy for privilege assignment and system access // capabilities. // Status = LsapDbInstallAccountObjects(); if (!NT_SUCCESS(Status)) { KdPrint(("LSA DB INSTALL: Installation of account objects failed.\n" " Status: 0x%lx\n", Status)); goto InstallPolicyObjectError; } // // Set up the account domain and primary domain information // ONLY if the real setup wasn't run. In that case, we are // doing a pseudo setup as part of a developer's first boot. // if (!LsapSetupWasRun) { LsapDbSetDomainInfo( &NextAttribute, &AttributeCount ); } if (LsapProductType == NtProductLanManNt) { // // Audit log information was set for WinNt product // in pass 1. Change if necessary in this pass. // InitialAuditLogInformation.MaximumLogSize = 20*1024; InitialAuditLogInformation.AuditLogPercentFull = 0; InitialAuditLogInformation.AuditRetentionPeriod.LowPart = 0x823543; InitialAuditLogInformation.AuditRetentionPeriod.HighPart = 0; InitialAuditLogInformation.AuditLogFullShutdownInProgress = FALSE; InitialAuditLogInformation.TimeToShutdown.LowPart = 0x46656; InitialAuditLogInformation.TimeToShutdown.HighPart = 0; LsapDbInitializeAttribute( NextAttribute, &LsapDbNames[PolAdtLg], &InitialAuditLogInformation, sizeof (POLICY_AUDIT_LOG_INFO), FALSE ); NextAttribute++; AttributeCount++; } if (AttributeCount > 0) { Status = LsapDbReferenceObject( LsapDbHandle, 0, PolicyObject, PolicyObject, LSAP_DB_LOCK | LSAP_DB_START_TRANSACTION ); if (!NT_SUCCESS(Status)) { LsapDiagPrint( DB_INIT, ("LSA (init): Internal reference of Policy object failed.\n" " Status of LsapDbReferenceObject == 0x%lx\n", Status) ); goto InstallPolicyObjectError; } ObjectReferenced = TRUE; Status = LsapDbWriteAttributesObject( LsapDbHandle, Attributes, AttributeCount ); if (!NT_SUCCESS(Status)) { LsapDiagPrint( DB_INIT, ("LSA (init): Update of Policy attributes failed.\n" " Attributes:\n\n" " Count: %d\n" " Array Address: 0x%lx", AttributeCount, Attributes) ); goto InstallPolicyObjectError; } Status = LsapDbDereferenceObject( &LsapDbHandle, PolicyObject, PolicyObject, (LSAP_DB_LOCK | LSAP_DB_FINISH_TRANSACTION), (SECURITY_DB_DELTA_TYPE) 0, STATUS_SUCCESS ); if (!NT_SUCCESS(Status)) { LsapLogError( "LsapDbInstallPolicyObject: Pass 2 DB init failed. 0x%lx\n", Status ); goto InstallPolicyObjectError; } ObjectReferenced = FALSE; } } InstallPolicyObjectFinish: // // If necessary, dereference the Policy Object. // if (ObjectReferenced) { Status = LsapDbDereferenceObject( &LsapDbHandle, PolicyObject, PolicyObject, (LSAP_DB_LOCK | LSAP_DB_FINISH_TRANSACTION), (SECURITY_DB_DELTA_TYPE) 0, Status ); } return(Status); InstallPolicyObjectError: if (Pass == 1) { LsapLogError( "LsapDbInstallPolicyObject: Pass 1 DB init failed. 0x%lx\n", Status ); } else { LsapLogError( "LsapDbInstallPolicyObject: Pass 2 DB init failed. 0x%lx\n", Status ); } goto InstallPolicyObjectFinish; } NTSTATUS LsapDbGetConfig ( IN HANDLE KeyHandle, IN PWSTR Name, OUT PUNICODE_STRING Value ) /*++ Routine Description: This routine obtains configuration information from the registry. Arguments: KeyHandle - handle to registry key node containing value. Name - The name of a value under the specifed key node. Value - Fills in the string with the value of the parameter. The returned string is zero terminated. The buffer is allocated in Process Heap and should be deallocated by the caller. Return Value: STATUS_SUCCESS - If the operation was successful. STATUS_NO_MEMORY - There wasn't enough memory to allocate a buffer to contain the returned information. STATUS_OBJECT_NAME_NOT_FOUND - The specifed section or the specified keyword could not be found. --*/ { NTSTATUS Status; UNICODE_STRING ValueName; ULONG Length, ResultLength; PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; RtlInitUnicodeString( &ValueName, Name ); Length = 512; KeyValueInformation = RtlAllocateHeap( RtlProcessHeap(), 0, Length ); if (KeyValueInformation == NULL) { Status = STATUS_NO_MEMORY; } else { Status = NtQueryValueKey( KeyHandle, &ValueName, KeyValuePartialInformation, KeyValueInformation, Length, &ResultLength ); if (NT_SUCCESS( Status )) { if (KeyValueInformation->Type != REG_SZ) { Status = STATUS_OBJECT_NAME_NOT_FOUND; } } } if (NT_SUCCESS( Status )) { Value->MaximumLength = (USHORT)(KeyValueInformation->DataLength); if (Value->MaximumLength >= sizeof(UNICODE_NULL)) { Value->Length = (USHORT)KeyValueInformation->DataLength - sizeof( UNICODE_NULL); } else { Value->Length = 0; } Value->Buffer = (PWSTR)KeyValueInformation; RtlMoveMemory( Value->Buffer, KeyValueInformation->Data, Value->Length ); Value->Buffer[ Value->Length / sizeof( WCHAR ) ] = UNICODE_NULL; KeyValueInformation = NULL; } else { #if DEVL DbgPrint( "LSA DB INSTALL: No '%wZ' value in registry - Status == %x\n", &ValueName, Status); #endif //DEVL } if ( KeyValueInformation != NULL ) { RtlFreeHeap( RtlProcessHeap(), 0, KeyValueInformation ); } return Status; } NTSTATUS LsapDbGetNextValueToken( IN PUNICODE_STRING Value, IN OUT PULONG ParseContext, OUT PUNICODE_STRING *ReturnString ) /*++ Routine Description: This routine is used to isolate the next token in a registry value. The token is returned in a single heap buffer containing both the STRING and the Buffer of that string containing the token. The caller of this routine is responsible for deallocating the buffer when it is no longer needed. The string, although counted, will also be null terminated. Arguments: Value - Supplies the value line being parsed. ParseContext - Is a pointer to a context state value. The first time this routine is called for a particular Value line, the value pointed to should be zero. Thereafter, the value returned from the previous call should be passed. ReturnString - Returns a pointer to the allocated string. Return Value: STATUS_SUCCESS - indicates the next token has been isolated. STATUS_INVALID_PARAMTER_1 - Indicates there were no more tokens in the Value line. STATUS_NO_MEMORY - memory could not be allocated for the token. --*/ { ULONG i, j; ULONG TokenLength; ULONG AllocSize; // // Get to the beginning of the next token // for ( i = *ParseContext; i < (Value->Length/sizeof(WCHAR)) && (Value->Buffer[i] == L' ' || Value->Buffer[i] == L'\t'); i++ ) ; // // see if we ran off the end of the string.. // if (i >= (Value->Length/sizeof(WCHAR))) { return STATUS_INVALID_PARAMETER_1; } // // Now search for the end of the token // for ( j = i + 1; j < (Value->Length/sizeof(WCHAR)) && Value->Buffer[j] != L' ' && Value->Buffer[j] != L'\t'; j++ ) ; *ParseContext = j; // // We've either reached the end of the string, or found the end of the // token. // // // If the caller actually wants the string returned, // allocate and copy it. // if ( ARGUMENT_PRESENT( ReturnString ) ) { UNICODE_STRING SourceString; PUNICODE_STRING LocalString; TokenLength = (j-i) * sizeof(WCHAR); AllocSize = sizeof(UNICODE_STRING) + (TokenLength + sizeof( UNICODE_NULL ) + 4); LocalString = RtlAllocateHeap( RtlProcessHeap(), 0, AllocSize ); if ( LocalString == NULL ) { DbgPrint("LSA DB INSTALL: LsapDbGetNextValueToken: Not enough memory %ld\n", AllocSize); return STATUS_NO_MEMORY; } LocalString->MaximumLength = (USHORT)(TokenLength + sizeof( UNICODE_NULL )); LocalString->Length = (USHORT)TokenLength; LocalString->Buffer = (PWCHAR)(LocalString + 1); // // Now copy the token // SourceString.MaximumLength = LocalString->Length; SourceString.Length = LocalString->Length; SourceString.Buffer = &Value->Buffer[i]; RtlCopyUnicodeString( LocalString, &SourceString ); // // Add a null terminator // LocalString->Buffer[LocalString->Length / sizeof( UNICODE_NULL )] = UNICODE_NULL; *ReturnString = LocalString; } return STATUS_SUCCESS; } VOID LsapDbSetDomainInfo( IN PLSAP_DB_ATTRIBUTE *NextAttribute, IN ULONG *AttributeCount ) /* This routine is only used for the pseudo setup for internal developer's use. In a real product installation/setup situation, The functionality performed by this routine is performed by the text-mode setup supplemented by the network setup. This routine must establish values for the AccountDomain and PrimaryDomain attributes of the Policy object. These attributes must be configured as follows: I. Standalone Win-NT product AccountDomainName = "Account" AccountDomainSid = (value assigned by user) PrimaryDomainName = Name of domain to use for browsing (this is optional in this case) PrimaryDomainSid = (None) II. Non-Standalone Win-NT product AccountDomainName = "Account" AccountDomainSid = (value assigned by user) PrimaryDomainName = (Primary domain's name) PrimaryDomainSid = (Primary domain's SID) III. LanMan-NT product AccountDomainName = (Primary domain's name) AccountDomainSid = (Primary domain's SID) PrimaryDomainName = (Primary domain's name) PrimaryDomainSid = (Primary domain's SID) This routine only does (II) and (III). The real setup must be capable of doing (I) as well. */ { NTSTATUS Status; NT_PRODUCT_TYPE ProductType; BOOLEAN ProductExplicitlySpecified; UNICODE_STRING PrimaryDomainName, AccountDomainName; PSID PrimaryDomainSid, AccountDomainSid; HANDLE KeyHandle = NULL; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; ULONG TempULong = 0 ; SID_IDENTIFIER_AUTHORITY TmppAuthority; ULONG DomainSubAuthorities[SID_MAX_SUB_AUTHORITIES]; UCHAR DomainSubAuthorityCount = 0; ULONG i; ULONG Context = 0; PUNICODE_STRING Rid; ULONG Size; UNICODE_STRING DomainId; PrimaryDomainSid = NULL; AccountDomainSid = NULL; PrimaryDomainName.Buffer = NULL; DomainId.Buffer = NULL; // // Get the product type // ProductExplicitlySpecified = RtlGetNtProductType( &ProductType ); #if DBG if (ProductType == NtProductLanManNt) { DbgPrint("LSA DB INSTALL: Configuring LSA database for LanManNt system.\n"); } else { DbgPrint("LSA DB INSTALL: Configuring LSA database for WinNt or Dedicated Server product.\n"); } #endif //DBG // // Open a handle to the registry key node that contains the // interesting domain values (name, id, and account id) // RtlInitUnicodeString( &KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters" ); InitializeObjectAttributes( &ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenKey( &KeyHandle, KEY_READ, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { #if DEVL DbgPrint( "LSA DB INSTALL: Unable to access registry key (%wZ) - Status == %x\n", &KeyName, Status ); #endif // DBG goto Exit; } // // Get the primary domain name from the registry // Status = LsapDbGetConfig(KeyHandle, L"Domain", &PrimaryDomainName); if ( !NT_SUCCESS( Status ) ) { goto Exit; } // // get the primary domain's SID // Status = LsapDbGetConfig(KeyHandle, L"DomainId", &DomainId ); if ( !NT_SUCCESS( Status ) ) { goto Exit; } // // Get the Authority ID from the registry // for (i=0; i < sizeof(TmppAuthority.Value)/sizeof(TmppAuthority.Value[0]); i++ ) { Status = LsapDbGetNextValueToken( &DomainId, &Context, &Rid ); if (NT_SUCCESS( Status )) { Status = RtlUnicodeStringToInteger(Rid, 10, &TempULong ); RtlFreeHeap( RtlProcessHeap(), 0, Rid ); } if ( !NT_SUCCESS( Status ) ) { #if DBG DbgPrint("LSA DB INSTALL: domainid - must have at least %ld subauthorities\n", sizeof(TmppAuthority.Value)/sizeof(TmppAuthority.Value[0])); #endif //DBG goto Exit; } TmppAuthority.Value[i] = (UCHAR)TempULong; } // // Get some subauthorities from the registry // for (i=0; ; i++ ) { Status = LsapDbGetNextValueToken( &DomainId, &Context, &Rid ); if (NT_SUCCESS( Status )) { Status = RtlUnicodeStringToInteger(Rid, 10, &TempULong ); RtlFreeHeap( RtlProcessHeap(), 0, Rid ); } if ( Status == STATUS_INVALID_PARAMETER_1 ) { break; } if ( !NT_SUCCESS( Status )) { goto Exit; } if ( i >= sizeof(DomainSubAuthorities)/sizeof(DomainSubAuthorities[0]) ) { #if DBG DbgPrint("LSA DB INSTALL: domainid - " "Too many Domain subauthorities specified (%ld maximum).\n", sizeof(DomainSubAuthorities)/sizeof(DomainSubAuthorities[0])); #endif //DBG goto Exit; } DomainSubAuthorities[i] = TempULong; DomainSubAuthorityCount ++; } // // Allocate memory to put the domain id in. // Size = RtlLengthRequiredSid( DomainSubAuthorityCount ); PrimaryDomainSid = RtlAllocateHeap( RtlProcessHeap(), 0, Size ); if (PrimaryDomainSid == NULL) { goto Exit; } Status = RtlInitializeSid( PrimaryDomainSid, &TmppAuthority, DomainSubAuthorityCount ); if ( !NT_SUCCESS( Status )) { goto Exit; } for ( i=0; i < (ULONG) DomainSubAuthorityCount; i++ ) { *(RtlSubAuthoritySid(PrimaryDomainSid, i)) = DomainSubAuthorities[i]; } if (ProductType != NtProductLanManNt) { DomainSubAuthorityCount = 0; Context = 0; // // if the system is a WinNt product, then get the account domain // SID from the registry info and set a well known name ("ACCOUNT"). // RtlInitUnicodeString(&AccountDomainName,L"Account"); // // Free old DomainId data if it has been allocated previously // if (DomainId.Buffer != NULL) { RtlFreeHeap( RtlProcessHeap(), 0, DomainId.Buffer ); DomainId.Buffer = NULL; } Status = LsapDbGetConfig(KeyHandle, L"AccountDomainId", &DomainId ); if ( !NT_SUCCESS( Status ) ) { goto Exit; } // // Get the Authority ID from the registry // for (i=0; i= sizeof(DomainSubAuthorities)/sizeof(DomainSubAuthorities[0]) ) { #if DBG DbgPrint("MsV1_0: NT.CFG: domainid - Too many Domain subauthorities specified (%ld maximum).\n", sizeof(DomainSubAuthorities)/sizeof(DomainSubAuthorities[0])); #endif //DBG goto Exit; } DomainSubAuthorities[i] = TempULong; DomainSubAuthorityCount ++; } // // Allocate memory to put the domain id in. // Size = RtlLengthRequiredSid( DomainSubAuthorityCount ); AccountDomainSid = RtlAllocateHeap( RtlProcessHeap(), 0, Size ); if (AccountDomainSid == NULL) { goto Exit; } RtlInitializeSid( AccountDomainSid, &TmppAuthority, DomainSubAuthorityCount ); for ( i=0; i < (ULONG) DomainSubAuthorityCount; i++ ) { *(RtlSubAuthoritySid(AccountDomainSid, i)) = DomainSubAuthorities[i]; } } else { // // Otherwise, the account domain is set up just like the // primary domain // AccountDomainName = PrimaryDomainName; Size = RtlLengthSid(PrimaryDomainSid); AccountDomainSid = RtlAllocateHeap( RtlProcessHeap(), 0, Size ); if (AccountDomainSid == NULL) { goto Exit; } Status = RtlCopySid( Size, AccountDomainSid, PrimaryDomainSid); if ( !NT_SUCCESS( Status ) ) { goto Exit; } } // // Now add the attributes to be initialized in the policy object... // // // Primary domain name/sid // Status = LsapDbMakeUnicodeAttribute( &PrimaryDomainName, &LsapDbNames[PolPrDmN], (*NextAttribute) ); if ( !NT_SUCCESS( Status )) { goto Exit; } (*NextAttribute)++; (*AttributeCount)++; Status = LsapDbMakeSidAttribute( PrimaryDomainSid, &LsapDbNames[PolPrDmS], (*NextAttribute) ); if ( !NT_SUCCESS( Status )) { goto Exit; } PrimaryDomainSid = NULL; (*NextAttribute)++; (*AttributeCount)++; // // Account domain name/sid // Status = LsapDbMakeUnicodeAttribute( &AccountDomainName, &LsapDbNames[PolAcDmN], (*NextAttribute) ); if ( !NT_SUCCESS( Status )) { goto Exit; } (*NextAttribute)++; (*AttributeCount)++; Status = LsapDbMakeSidAttribute( AccountDomainSid, &LsapDbNames[PolAcDmS], (*NextAttribute) ); if ( !NT_SUCCESS( Status )) { goto Exit; } AccountDomainSid = NULL; (*NextAttribute)++; (*AttributeCount)++; Exit: if (KeyHandle != NULL) { NtClose(KeyHandle); } if (DomainId.Buffer != NULL) { RtlFreeHeap( RtlProcessHeap(), 0, DomainId.Buffer ); } if (PrimaryDomainName.Buffer != NULL) { RtlFreeHeap( RtlProcessHeap(), 0, PrimaryDomainName.Buffer); } if (PrimaryDomainSid != NULL) { RtlFreeHeap (RtlProcessHeap(), 0, PrimaryDomainSid); } if (AccountDomainSid != NULL) { RtlFreeHeap (RtlProcessHeap(), 0, AccountDomainSid); } }