Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1288 lines
29 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
lsainit.c
Abstract:
Local Security Authority Protected Subsystem - Initialization
Author:
Scott Birrell (ScottBi) March 12, 1991
Environment:
Revision History:
--*/
#include <lsapch2.h>
#include <secur32p.h>
#include <ntddksec.h>
#include <ntdsa.h>
#include "adtp.h"
#include "spinit.h"
#include "efssrv.hxx"
#include "dssetp.h"
#include "sidcache.h"
#include "klpcstub.h"
#include "lsawmi.h"
#include "dpapiprv.h"
//
// Name of event which says that the LSA RPC server is ready
//
#define LSA_RPC_SERVER_ACTIVE L"LSA_RPC_SERVER_ACTIVE"
/////////////////////////////////////////////////////////////////////////
// //
// Shared Global Variables //
// //
/////////////////////////////////////////////////////////////////////////
#if LSAP_DIAGNOSTICS
//
// LSA Global Controls
//
ULONG LsapGlobalFlag = 0;
#endif //LSAP_DIAGNOSTICS
//
// Handles used to talk to SAM directly.
// Also, a flag to indicate whether or not the handles are valid.
//
BOOLEAN LsapSamOpened = FALSE;
SAMPR_HANDLE LsapAccountDomainHandle;
SAMPR_HANDLE LsapBuiltinDomainHandle;
DWORD LsapGlobalRestrictNullSessions = TRUE;
DWORD LsapGlobalRestrictAnonymous = TRUE;
DWORD LsapGlobalSetAdminOwner = TRUE;
PWSTR pszPreferred;
//
// Handle to KSecDD device, for passing down ioctls.
//
HANDLE KsecDevice ;
//
// For outside calls (e.g. RPC originated) CallInfo won't be there,
// but some helper functions will look for it. This is a default one
// that can be used.
//
LSA_CALL_INFO LsapDefaultCallInfo ;
/////////////////////////////////////////////////////////////////////////
// //
// Module-Wide variables //
// //
/////////////////////////////////////////////////////////////////////////
BOOLEAN LsapHealthCheckingEnabled = FALSE;
BOOLEAN LsapPromoteInitialized = FALSE;
/////////////////////////////////////////////////////////////////////////
// //
// Internal routine prototypes //
// //
/////////////////////////////////////////////////////////////////////////
NTSTATUS
LsapActivateRpcServer();
DWORD
LsapRpcServerThread(
LPVOID Parameter
);
NTSTATUS
LsapInstallationPause();
VOID
LsapSignalRpcIsActive();
NTSTATUS
LsapDsInitializePromoteInterface(
VOID
);
//
// Open the KSec Device
//
VOID
LsapOpenKsec(
VOID
)
{
NTSTATUS Status ;
UNICODE_STRING String ;
OBJECT_ATTRIBUTES ObjA ;
IO_STATUS_BLOCK IoStatus ;
RtlInitUnicodeString( &String, DD_KSEC_DEVICE_NAME_U );
InitializeObjectAttributes( &ObjA,
&String,
0,
0,
0);
Status = NtOpenFile( &KsecDevice,
GENERIC_READ | GENERIC_WRITE,
&ObjA,
&IoStatus,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0 );
if ( !NT_SUCCESS( Status ) )
{
DebugLog(( DEB_ERROR, "FAILED to open %ws, status %x\n",
String.Buffer, Status ));
return;
}
Status = NtDeviceIoControlFile(
KsecDevice,
NULL,
NULL,
NULL,
&IoStatus,
IOCTL_KSEC_CONNECT_LSA,
NULL,
0,
NULL,
0 );
if ( !NT_SUCCESS( Status ) )
{
DebugLog(( DEB_ERROR, "FAILED to send ioctl, status %x\n", Status ));
}
else
{
LsapFindEfsSession();
}
}
/////////////////////////////////////////////////////////////////////////
// //
// Routines //
// //
/////////////////////////////////////////////////////////////////////////
VOID
FixupEnvironment(
VOID
)
{
WCHAR Root[ MAX_PATH ];
DWORD Length;
PWCHAR PostFix = L"\\System32";
BOOL RetVal;
Length = GetEnvironmentVariable(L"SystemRoot", Root, MAX_PATH);
ASSERT(Length && Length < MAX_PATH); // Let someone know if the call doesn't work
wcsncat(Root, PostFix, MAX_PATH - Length - 1);
ASSERT(MAX_PATH - Length > wcslen (PostFix)); // Let someone know if buffer is too small
DebugLog((DEB_TRACE_INIT, "Setting PATH to %ws\n", Root));
RetVal = SetEnvironmentVariable( TEXT("Path"), Root);
ASSERT(RetVal);
}
VOID
LsapSetupTuningParameters(
VOID
)
{
NT_PRODUCT_TYPE ProductType;
SYSTEM_INFO si;
HKEY LsaKey ;
int err ;
ULONG Value ;
ULONG Type ;
ULONG Size ;
ULONG GlobalReturn = 0 ;
NTSTATUS scRet ;
LsaTuningParameters.ThreadLifespan = 60 ;
LsaTuningParameters.SubQueueLifespan = 30 ;
LsaTuningParameters.Options = TUNE_TRIM_WORKING_SET ;
//
// setup the preferred critsec spin count.
//
GetSystemInfo( &si );
LsaTuningParameters.CritSecSpinCount = 1000 * si.dwNumberOfProcessors;
if( LsaTuningParameters.CritSecSpinCount > 32000 )
{
LsaTuningParameters.CritSecSpinCount = 32000;
} else if( LsaTuningParameters.CritSecSpinCount < 1000 )
{
LsaTuningParameters.CritSecSpinCount = 1000;
}
scRet = RtlGetNtProductType( &ProductType );
if ( NT_SUCCESS( scRet ) )
{
if ( ProductType != NtProductWinNt )
{
LsaTuningParameters.ThreadLifespan = 15 * 60 ;
LsaTuningParameters.SubQueueLifespan = 5 * 60 ;
LsaTuningParameters.Options = 0 ;
if ( ProductType == NtProductLanManNt )
{
LsaTuningParameters.Options |= TUNE_PRIVATE_HEAP ;
//
// On DCs, link to the real version of the NTDSA
// save and restore.
//
GetDsaThreadState = (DSA_THSave *) THSave ;
RestoreDsaThreadState = (DSA_THRestore *) THRestore ;
}
}
}
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
TEXT("System\\CurrentControlSet\\Control\\Lsa"),
0,
KEY_READ | KEY_WRITE,
&LsaKey );
if ( err == 0 )
{
Value = GetCurrentProcessId();
RegSetValueEx(
LsaKey,
TEXT("LsaPid"),
0,
REG_DWORD,
(PUCHAR) &Value,
sizeof( DWORD ) );
Size = sizeof(DWORD);
err = RegQueryValueEx( LsaKey,
TEXT("GeneralThreadLifespan"),
0,
&Type,
(PUCHAR) &Value,
&Size );
if ( err == 0 )
{
LsaTuningParameters.ThreadLifespan = Value ;
}
Size = sizeof( DWORD );
err = RegQueryValueEx( LsaKey,
TEXT("DedicatedThreadLifespan"),
0,
&Type,
(PUCHAR) &Value,
&Size );
if ( err == 0 )
{
LsaTuningParameters.SubQueueLifespan = Value ;
}
Size = sizeof( DWORD );
err = RegQueryValueEx( LsaKey,
TEXT("HighPriority"),
0,
&Type,
(PUCHAR) &Value,
&Size );
if ( err == 0 )
{
if ( Value )
{
LsaTuningParameters.Options |= TUNE_SRV_HIGH_PRIORITY ;
}
}
Size = sizeof( DWORD );
err = RegQueryValueEx( LsaKey,
TEXT("CritSecSpinCount"),
0,
&Type,
(PUCHAR) &Value,
&Size );
if ( err == 0 )
{
if ( Value && (Type == REG_DWORD) )
{
LsaTuningParameters.CritSecSpinCount = Value;
}
}
RegCloseKey( LsaKey );
}
DebugLog(( DEB_TRACE_INIT, "Tuning parameters:\n" ));
DebugLog(( DEB_TRACE_INIT, " Thread Lifespan %d sec\n",
LsaTuningParameters.ThreadLifespan ));
DebugLog(( DEB_TRACE_INIT, " SubQueue Lifespan %d sec\n",
LsaTuningParameters.SubQueueLifespan ));
DebugLog(( DEB_TRACE_INIT, " Options:\n" ));
}
NTSTATUS
LsapInitLsa(
)
/*++
Routine Description:
This process is activated as a standard SM subsystem. Initialization
completion of a SM subsystem is indicated by having the first thread
exit with status.
This function initializes the LSA. The initialization procedure comprises
the following steps:
o LSA Heap Initialization
o LSA Command Server Initialization
o LSA Database Load
o Reference Monitor State Initialization
o LSA RPC Server Initialization
o LSA Auditing Initialization
o LSA Authentication Services Initialization
o Wait for Setup to complete (if necessary)
o LSA database initialization (product type-specific)
o Start backgroup thread to register WMI tracing guids
Any failure in any of the above steps is fatal and causes the LSA
process to terminate. The system must be aborted.
Arguments:
None.
Return Value:
NTSTATUS - Standard Nt Result Code.
--*/
{
NTSTATUS Status;
BOOLEAN BooleanStatus = TRUE;
DWORD EFSRecoverThreadID;
HANDLE EFSThread ;
SYSTEM_INFO SysInfo ;
#if DBG
InitDebugSupport();
#endif
FixupEnvironment();
//
// Optional break point
//
BreakOnError(BREAK_ON_BEGIN_INIT);
//
// Init the TLS indices
//
(void) InitThreadData();
//
// Initialize the stack allocator
//
SafeAllocaInitialize(
SAFEALLOCA_USE_DEFAULT,
SAFEALLOCA_USE_DEFAULT,
LsapAllocatePrivateHeapNoZero,
LsapFreePrivateHeap
);
LsapSetupTuningParameters();
#if DBG
LsaTuningParameters.Options |= TUNE_PRIVATE_HEAP ;
#endif
GetSystemInfo( &SysInfo );
LsapPageSize = SysInfo.dwPageSize ;
LsapUserModeLimit = (ULONG_PTR) SysInfo.lpMaximumApplicationAddress ;
LsapHeapInitialize( ((LsaTuningParameters.Options & TUNE_PRIVATE_HEAP ) != 0) );
//
// Initialize this thread:
//
SpmpThreadStartup();
//
// Update the SSPI cache
//
SecCacheSspiPackages();
//
// Initialize session tracking:
//
if (!InitSessionManager())
{
DebugLog((DEB_ERROR, "InitSessionManager failed?\n"));
Status = STATUS_INTERNAL_ERROR;
goto InitLsaError;
}
//
// Initialize misc. global variables:
//
LsapDefaultCallInfo.Session = pDefaultSession ;
LsapDefaultCallInfo.LogContext = NULL ;
LsapDefaultCallInfo.LogonId.HighPart = 0 ;
LsapDefaultCallInfo.LogonId.LowPart = 999 ;
LsapDefaultCallInfo.InProcCall = TRUE ;
LsapDefaultCallInfo.Allocs = MAX_BUFFERS_IN_CALL ;
#if defined(REMOTE_BOOT)
//
// Initilize the state indicating whether this is a remote boot machine.
//
LsapDbInitializeRemoteBootState();
#endif // defined(REMOTE_BOOT)
//
// Initialize scavenger thread control
//
if ( !LsapInitializeScavenger() )
{
DebugLog(( DEB_ERROR, "Could not initialize scavenger thread\n"));
Status = STATUS_INTERNAL_ERROR ;
goto InitLsaError ;
}
//
// Start up the thread pool for support for LPC.
//
if (!InitializeThreadPool())
{
DebugLog((DEB_ERROR, "Could not init thread pool\n"));
Status = STATUS_INTERNAL_ERROR;
goto InitLsaError;
}
DebugLog((DEB_TRACE_INIT, "Current TraceLevel is %x\n", SPMInfoLevel));
//
// Load parameters from Registry:
//
Status = LoadParameters( FALSE );
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
//
// Initialize a copy of the Well-Known Sids, etc. for use by
// the LSA.
//
Status = LsapDbInitializeWellKnownValues();
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
//
// If this is a time-checking build, load the timer support
// functions and initialize them.
//
#ifdef TIME_SPM
InitTimer();
#endif
//
// If we're going to be in a setup phase, tag it.
//
SetupPhase = SpmpIsSetupPass();
//
// Tell base/wincon how to shut us down.
// First, tell base to shut us down as late in the game as possible.
SetProcessShutdownParameters(SPM_SHUTDOWN_VALUE, SHUTDOWN_NORETRY);
//
// And, tell them what function to call when we are being shutdown:
//
SetConsoleCtrlHandler(SpConsoleHandler, TRUE);
//
// Set security on the synchronization event
//
Status = LsapBuildSD(BUILD_KSEC_SD, NULL);
if (FAILED(Status))
{
DebugLog((DEB_ERROR,"Failed to set Ksec security: 0x%x\n",Status));
goto InitLsaError;
}
//
// Perform LSA Command Server Initialization. This involves creating
// an LPC port called the LSA Command Server Port so that the Reference
// monitor can send commands to the LSA via the port. After the port
// is created, an event created by the Reference Monitor is signalled,
// so that the Reference Monitor can proceed to connect to the port.
Status = LsapRmInitializeServer();
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
//
// Perform LSA Database Server Initialization - Pass 1.
// This initializes the non-product-type-specific information.
//
Status = LsapDbInitializeServer(1);
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
//
// Perform Auditing Initialization - Pass 1.
//
Status = LsapAdtInitialize();
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
Status = LsapAdtObjsInitialize();
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
//
// Load packages:
//
// The System Logon session must be present before (at least) the
// NegpackageLoad routine is called, so we can set it's creating package
// id, otherwise the package id is 0, which is normally ok, but when a
// machine is joined to a pre NT5 domain, this will mean that we
// will not do NTLM in a system logon session.
if ( !LsapLogonSessionInitialize() )
{
goto InitLsaError ;
}
Status = LoadPackages( ppszPackages,
ppszOldPkgs,
pszPreferred );
if (FAILED(Status))
{
DebugLog((DEB_ERROR, "Error loading packages, terminating (0x%08x)\n",
Status));
goto InitLsaError;
}
//
// Initialize the credential manager
//
Status = CredpInitialize();
if ( !NT_SUCCESS( Status )) {
goto InitLsaError;
}
//
// Initialize data for System LogonID (999):
//
InitSystemLogon();
//
// Perform RPC Server Initialization.
//
Status = LsapRPCInit();
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
//
// Initialize Authentication Services
//
if (!LsapAuInit()) {
Status = STATUS_UNSUCCESSFUL;
goto InitLsaError;
}
//
// Initialize the sid cache
//
Status = LsapDbInitSidCache();
if (!NT_SUCCESS(Status)) {
DebugLog((DEB_ERROR, "Error initializing sid cache: 0x%x\n",Status));
goto InitLsaError;
}
//
// Initialize LPC Server to talk to the FSPs waiting on the device driver
//
Status = StartLpcThread();
if (FAILED(Status))
{
DebugLog((DEB_ERROR, "Error starting LPC thread, no DD support (0x%08x)\n",
Status));
goto InitLsaError;
}
//
// open ksec and have it connect back to us in our own context.
//
LsapOpenKsec();
//
// Optional breakpoint when initialization complete
//
BreakOnError(BREAK_ON_BEGIN_END);
//
// Start processing RPC calls
//
Status = LsapActivateRpcServer();
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
//
// Initialize DPAPI
//
Status = DPAPIInitialize(&LsapSecpkgFunctionTable);
if ( !NT_SUCCESS( Status )) {
goto InitLsaError;
}
//
// Pause for installation if necessary
//
Status = LsapInstallationPause();
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
//
// Perform LSA Database Server Initialization - Pass 2.
// This initializes the product-type-specific information.
//
Status = LsapDbInitializeServer(2);
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
//
// Initialize EFS
//
( VOID )EfsServerInit();
//
// If EfsServerInit() fails because of policy & etc.
// the recovery thread should not be run.
//
EFSThread = CreateThread( NULL,
0,
EFSRecover,
NULL,
0,
&EFSRecoverThreadID );
if ( EFSThread )
{
CloseHandle( EFSThread );
}
//
// Initialize the Setup APIs
//
if ( !LsapPromoteInitialized ) {
DsRolepInitialize();
}
Status = LsapStartWmiTraceInitThread();
if (!NT_SUCCESS(Status)) {
goto InitLsaError;
}
InitLsaFinish:
return(Status);
InitLsaError:
goto InitLsaFinish;
}
NTSTATUS
LsapActivateRpcServer( VOID )
/*++
Routine Description:
This function creates a thread for the RPC server.
The new Thread then goes on to activate the RPC server,
which causes RPC calls to be delivered when recieved.
Arguments:
None.
Return Value:
STATUS_SUCCESS - The thread was successfully created.
Other status values that may be set by CreateThread().
--*/
{
NTSTATUS Status;
// Start listening for remote procedure calls. The first
// argument to RpcServerListen is the minimum number of call
// threads to create; the second argument is the maximum number
// of concurrent calls allowed. The final argument indicates that
// this routine should not wait. After everything has been initialized,
// we return.
Status = I_RpcMapWin32Status(RpcServerListen(1, 1234, 1));
ASSERT( Status == RPC_S_OK );
//
// Set event which signals that RPC server is available.
//
LsapSignalRpcIsActive();
return(STATUS_SUCCESS);
}
NTSTATUS
LsapInstallationPause( VOID )
/*++
Routine Description:
This function checks to see if the system is in an
installation state. If so, it suspends further initialization
until the installation state is complete.
Installation state is signified by the existance of a well known
event.
Arguments:
None.
Return Value:
STATUS_SUCCESS - Proceed with initialization.
Other status values are unexpected.
--*/
{
if ( SpmpIsSetupPass() ) {
//
// The event exists - installation created it and will signal it
// when it is ok to proceed with security initialization.
//
LsapSetupWasRun = TRUE;
//
// Intialize the promotion interface
//
DsRolepInitialize();
LsapDsInitializePromoteInterface();
LsapPromoteInitialized = TRUE;
//
// Make sure we are not in mini-setup
//
if ( SpmpIsMiniSetupPass() ) {
LsapSetupWasRun = FALSE;
}
}
return( STATUS_SUCCESS );
}
BOOLEAN
LsaISetupWasRun(
)
/*++
Routine Description:
This function determines whether Setup was run.
Arguments:
None
Return Values
BOOLEAN - TRUE if setup was run, else FALSE
--*/
{
return(LsapSetupWasRun);
}
VOID
LsapSignalRpcIsActive(
)
/*++
Routine Description:
It creates the LSA_RPC_SERVER_ACTIVE event if one does not already exist
and signals it so that the service controller can proceed with LSA calls.
Arguments:
None.
Return Value:
None.
--*/
{
DWORD status;
HANDLE EventHandle;
EventHandle = CreateEventW(
NULL, // No special security
TRUE, // Must be manually reset
FALSE, // The event is initially not signalled
LSA_RPC_SERVER_ACTIVE
);
if (EventHandle == NULL) {
status = GetLastError();
//
// If the event already exists, the service controller beats us
// to creating it. Just open it.
//
if (status == ERROR_ALREADY_EXISTS) {
EventHandle = OpenEventW(
GENERIC_WRITE,
FALSE,
LSA_RPC_SERVER_ACTIVE
);
}
if (EventHandle == NULL) {
//
// Could not create or open the event. Nothing we can do...
//
return;
}
}
(VOID) SetEvent(EventHandle);
}
NTSTATUS
LsapGetAccountDomainInfo(
PPOLICY_ACCOUNT_DOMAIN_INFO *PolicyAccountDomainInfo
)
/*++
Routine Description:
This routine retrieves ACCOUNT domain information from the LSA
policy database.
Arguments:
PolicyAccountDomainInfo - Receives a pointer to a
POLICY_ACCOUNT_DOMAIN_INFO structure containing the account
domain info.
Return Value:
STATUS_SUCCESS - Succeeded.
Other status values that may be returned from:
LsaOpenPolicy()
LsaQueryInformationPolicy()
--*/
{
NTSTATUS Status;
//
// Query the account domain information
//
Status = LsarQueryInformationPolicy( LsapPolicyHandle,
PolicyAccountDomainInformation,
(PLSAPR_POLICY_INFORMATION *) PolicyAccountDomainInfo );
#if DBG
if ( NT_SUCCESS(Status) ) {
ASSERT( (*PolicyAccountDomainInfo) != NULL );
ASSERT( (*PolicyAccountDomainInfo)->DomainSid != NULL );
}
#endif // DBG
return(Status);
}
NTSTATUS
LsapOpenSam( VOID )
/*++
Routine Description:
This routine opens SAM for use during authentication. It
opens a handle to both the BUILTIN domain and the ACCOUNT domain.
Arguments:
None.
Return Value:
STATUS_SUCCESS - Succeeded.
--*/
{
return LsapOpenSamEx( FALSE );
}
NTSTATUS
LsapOpenSamEx(
BOOLEAN DuringStartup
)
/*++
Routine Description:
This routine opens SAM for use during authentication. It
opens a handle to both the BUILTIN domain and the ACCOUNT domain.
Arguments:
DuringStartup - TRUE if this is the call made during startup. In that case,
there is no need to wait on the SAM_STARTED_EVENT since the caller ensures
that SAM is started before the call is made.
Return Value:
STATUS_SUCCESS - Succeeded.
--*/
{
NTSTATUS Status, IgnoreStatus;
PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo;
SAMPR_HANDLE SamHandle;
if (LsapSamOpened == TRUE) { // Global variable
return(STATUS_SUCCESS);
}
//
// Make sure SAM has initialized
//
if ( !DuringStartup ) {
HANDLE EventHandle;
OBJECT_ATTRIBUTES EventAttributes;
UNICODE_STRING EventName;
LARGE_INTEGER Timeout;
RtlInitUnicodeString( &EventName, L"\\SAM_SERVICE_STARTED");
InitializeObjectAttributes( &EventAttributes, &EventName, 0, 0, NULL );
Status = NtOpenEvent( &EventHandle, SYNCHRONIZE, &EventAttributes );
if ( !NT_SUCCESS(Status)) {
if( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
//
// SAM hasn't created this event yet, let us create it now.
// SAM opens this event to set it.
//
Status = NtCreateEvent(
&EventHandle,
SYNCHRONIZE|EVENT_MODIFY_STATE,
&EventAttributes,
NotificationEvent,
FALSE // The event is initially not signaled
);
if( Status == STATUS_OBJECT_NAME_EXISTS ||
Status == STATUS_OBJECT_NAME_COLLISION ) {
//
// second change, if the SAM created the event before we
// do.
//
Status = NtOpenEvent( &EventHandle,
SYNCHRONIZE|EVENT_MODIFY_STATE,
&EventAttributes );
}
}
}
if (NT_SUCCESS(Status)) {
//
// See if SAM has signalled that he is initialized.
//
Timeout.QuadPart = -10000000; // 1000 seconds
Timeout.QuadPart *= 1000;
Status = NtWaitForSingleObject( EventHandle, FALSE, &Timeout );
IgnoreStatus = NtClose( EventHandle );
ASSERT(NT_SUCCESS(IgnoreStatus));
}
if ( !NT_SUCCESS(Status) || Status == STATUS_TIMEOUT ) {
return( STATUS_INVALID_SERVER_STATE );
}
}
//
// Get the member Sid information for the account domain
//
Status = LsapGetAccountDomainInfo( &PolicyAccountDomainInfo );
if (!NT_SUCCESS(Status)) {
return(Status);
}
//
// Get our handles to the ACCOUNT and BUILTIN domains.
//
Status = SamIConnect( NULL, // No server name
&SamHandle,
SAM_SERVER_CONNECT,
TRUE ); // Indicate we are privileged
if ( NT_SUCCESS(Status) ) {
//
// Open the ACCOUNT domain.
//
Status = SamrOpenDomain( SamHandle,
DOMAIN_ALL_ACCESS,
PolicyAccountDomainInfo->DomainSid,
&LsapAccountDomainHandle );
if (NT_SUCCESS(Status)) {
//
// Open the BUILTIN domain.
//
Status = SamrOpenDomain( SamHandle,
DOMAIN_ALL_ACCESS,
LsapBuiltInDomainSid,
&LsapBuiltinDomainHandle );
if (NT_SUCCESS(Status)) {
LsapSamOpened = TRUE;
} else {
IgnoreStatus = SamrCloseHandle( &LsapAccountDomainHandle );
ASSERT(NT_SUCCESS(IgnoreStatus));
}
}
IgnoreStatus = SamrCloseHandle( &SamHandle );
ASSERT(NT_SUCCESS(IgnoreStatus));
}
//
// Free the ACCOUNT domain information
//
LsaIFree_LSAPR_POLICY_INFORMATION(
PolicyAccountDomainInformation,
(PLSAPR_POLICY_INFORMATION) PolicyAccountDomainInfo );
return(Status);
}
NTSTATUS
LsapDsInitializePromoteInterface(
VOID
)
/*++
Routine Description:
Performs the initialization required for the Dc promotion/demotions apis, apart
from what is done during LsaInit
Arguments:
VOID
Return Values:
STATUS_SUCCESS -- Success.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
if ( LsapPromoteInitialized == FALSE ) { Status = DsRolepInitializePhase2(); } return( Status ); }