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.
 
 
 
 
 
 

449 lines
14 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1999-2001 Microsoft Corporation
//
// Module Name:
// CClusDB.cpp
//
// Description:
// Contains the definition of the CClusDB class.
//
// Maintained By:
// David Potter (DavidP) 14-JUN-2001
// Vij Vasu (Vvasu) 08-MAR-2000
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Include Files
//////////////////////////////////////////////////////////////////////////////
// The precompiled header.
#include "Pch.h"
// The header for this file
#include "CClusDB.h"
// For the CBaseClusterAction class
#include "CBaseClusterAction.h"
// For g_GenericSetupQueueCallback and other global functions
#include "GlobalFuncs.h"
// For CEnableThreadPrivilege
#include "CEnableThreadPrivilege.h"
// For ConvertStringSecurityDescriptorToSecurityDescriptor
#include <sddl.h>
//////////////////////////////////////////////////////////////////////////
// Macros definitions
//////////////////////////////////////////////////////////////////////////
// Section in the INF file that deals with cleaning up the cluster database
#define CLUSDB_CLEANUP_INF_SECTION_NAME L"ClusDB_Cleanup"
//////////////////////////////////////////////////////////////////////////////
//++
//
// CClusDB::CClusDB()
//
// Description:
// Constructor of the CClusDB class
//
// Arguments:
// pbcaParentActionIn
// Pointer to the base cluster action of which this action is a part.
//
// Return Value:
// None.
//
// Exceptions Thrown:
// CAssert
// If the parameters are incorrect.
//
// Any exceptions thrown by underlying functions
//
//--
//////////////////////////////////////////////////////////////////////////////
CClusDB::CClusDB(
CBaseClusterAction * pbcaParentActionIn
)
: m_pbcaParentAction( pbcaParentActionIn )
{
TraceFunc( "" );
if ( m_pbcaParentAction == NULL)
{
LogMsg( "[BC] Pointers to the parent action is NULL. Throwing an exception." );
THROW_ASSERT(
E_INVALIDARG
, "CClusDB::CClusDB() => Required input pointer in NULL"
);
} // if: the parent action pointer is NULL
TraceFuncExit();
} //*** CClusDB::CClusDB
//////////////////////////////////////////////////////////////////////////////
//++
//
// CClusDB::~CClusDB
//
// Description:
// Destructor of the CClusDB class.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
// Exceptions Thrown:
// Any exceptions thrown by underlying functions
//
//--
//////////////////////////////////////////////////////////////////////////////
CClusDB::~CClusDB( void )
{
TraceFunc( "" );
TraceFuncExit();
} //*** CClusDB::~CClusDB
//////////////////////////////////////////////////////////////////////////////
//++
//
// CClusDB::CreateHive
//
// Description:
// Creates the cluster cluster hive in the registry.
//
// Arguments:
// pbcaClusterActionIn
// Pointer to the CBaseClusterAction object which contains this object.
//
// Return Value:
// None.
//
// Exceptions Thrown:
// CRuntimeError
// If any of the APIs fail.
//
// Any that are thrown by the called functions.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
CClusDB::CreateHive( CBaseClusterAction * pbcaClusterActionIn )
{
TraceFunc( "" );
LogMsg( "[BC] Attempting to create the cluster hive in the registry." );
OBJECT_ATTRIBUTES oaClusterHiveKey;
OBJECT_ATTRIBUTES oaClusterHiveFile;
HRESULT hrStatus = STATUS_SUCCESS;
CStr strClusterHiveFileName( pbcaClusterActionIn->RStrGetClusterInstallDirectory() );
UNICODE_STRING ustrClusterHiveFileName;
UNICODE_STRING ustrClusterHiveKeyName;
PSECURITY_DESCRIPTOR psdHiveSecurityDescriptor = NULL;
strClusterHiveFileName += L"\\" CLUSTER_DATABASE_NAME;
LogMsg( "[BC] The cluster hive backing file is '%s'.", strClusterHiveFileName.PszData() );
//
// Enable the SE_RESTORE_PRIVILEGE.
//
// What we are doing here is that we are creating an object of
// type CEnableThreadPrivilege. This object enables the privilege
// in the constructor and restores it to its original state in the destructor.
//
CEnableThreadPrivilege etpAcquireRestorePrivilege( SE_RESTORE_NAME );
//
// Convert the DOS file name to NT file name.
// WARNING: This function call allocates memory in the RTL heap and it is not being
// assigned to a smart pointer. Make sure that we do not call any functions that
// could throw an exception till this memory is freed.
//
if ( RtlDosPathNameToNtPathName_U(
strClusterHiveFileName.PszData()
, &ustrClusterHiveFileName
, NULL
, NULL
)
== FALSE
)
{
LogMsg( "[BC] RtlDosPathNameToNtPathName failed. Returning %#08x as the error code.", STATUS_OBJECT_PATH_INVALID );
// Use the most appropriate error code.
hrStatus = STATUS_OBJECT_PATH_INVALID;
goto Cleanup;
} // if: we could not convert from the dos file name to the nt file name
InitializeObjectAttributes(
&oaClusterHiveFile
, &ustrClusterHiveFileName
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
RtlInitUnicodeString( &ustrClusterHiveKeyName, L"\\Registry\\Machine\\" CLUSREG_KEYNAME_CLUSTER );
InitializeObjectAttributes(
&oaClusterHiveKey
, &ustrClusterHiveKeyName
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
//
// This function creates an empty hive and the backing file and log. The calling thread must
// have the SE_RESTORE_PRIVILEGE privilege enabled.
//
hrStatus = THR( NtLoadKey2( &oaClusterHiveKey, &oaClusterHiveFile, REG_NO_LAZY_FLUSH ) );
// Free allocated memory before throwing exception.
RtlFreeHeap( RtlProcessHeap(), 0, ustrClusterHiveFileName.Buffer );
if ( NT_ERROR( hrStatus ) )
{
LogMsg( "[BC] NtLoadKey2 returned error code %#08x.", hrStatus );
goto Cleanup;
} // if: something went wrong with NtLoadKey2
TraceFlow( "NtLoadKey2 was successful." );
// Set the security descriptor on the hive.
{
DWORD sc;
BOOL fSuccess;
PACL paclDacl;
BOOL fIsDaclPresent;
BOOL fDefaultDaclPresent;
// Open the cluster hive key.
CRegistryKey rkClusterHive( HKEY_LOCAL_MACHINE, CLUSREG_KEYNAME_CLUSTER, WRITE_DAC );
// construct a DACL that is protected (P) from inheriting ACEs from
// its parent key (MACHINE). Add access allowed (A) ACEs for Local
// Admin (BA) and LocalSystem (SY) granting them full control (KA) and
// an ACE for NetworkService (NS), LocalService (LS), and
// authenticated users (AU) granting read only access (KR). Each ACE
// has container inherit (CI) set so subkeys will inherit the ACEs
// from this security descriptor.
fSuccess = ConvertStringSecurityDescriptorToSecurityDescriptor(
L"D:P(A;CI;KA;;;BA)(A;CI;KA;;;SY)(A;CI;KR;;;NS)(A;CI;KR;;;LS)(A;CI;KR;;;AU)"
, SDDL_REVISION_1
, &psdHiveSecurityDescriptor
, NULL
);
if ( fSuccess == FALSE )
{
sc = TW32( GetLastError() );
hrStatus = HRESULT_FROM_WIN32( sc );
LogMsg( "[BC] Error %#08x occurred trying to compose the security descriptor for the cluster hive.", sc );
goto Cleanup;
}
// get a pointer to the ACL in the SD and set the DACL on the root of
// the cluster hive.
fSuccess = GetSecurityDescriptorDacl(
psdHiveSecurityDescriptor
, &fIsDaclPresent
, &paclDacl
, &fDefaultDaclPresent
);
if ( fSuccess == FALSE )
{
sc = TW32( GetLastError() );
hrStatus = HRESULT_FROM_WIN32( sc );
LogMsg( "[BC] Error %#08x occurred trying to obtain the discretionary ACL from the cluster security descriptor.", sc );
goto Cleanup;
}
// This should always be the case since we just constructed the ACL in
// the Convert API call.
if ( fIsDaclPresent && !fDefaultDaclPresent )
{
sc = TW32( SetSecurityInfo(
rkClusterHive.HGetKey()
, SE_REGISTRY_KEY
, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION
, NULL // Owner SID
, NULL // Group SID
, paclDacl
, NULL // SACL
) );
if ( sc != ERROR_SUCCESS )
{
hrStatus = HRESULT_FROM_WIN32( sc );
LogMsg( "[BC] Error %#08x occurred trying to set the cluster hive security.", sc );
goto Cleanup;
} // if: ClRtlSetObjSecurityInfo failed
}
else
{
hrStatus = HRESULT_FROM_WIN32( ERROR_INVALID_SECURITY_DESCR );
LogMsg( "[BC] Cluster Hive discretionary ACL not correctly formatted." );
goto Cleanup;
}
// Flush the changes to the registry.
RegFlushKey( rkClusterHive.HGetKey() );
}
// At this point, the cluster hive has been created.
LogMsg( "[BC] The cluster hive has been created." );
Cleanup:
if ( psdHiveSecurityDescriptor )
{
LocalFree( psdHiveSecurityDescriptor );
}
if ( NT_ERROR( hrStatus ) )
{
LogMsg( "[BC] Error %#08x occurred trying to create the cluster hive. Throwing an exception.", hrStatus );
THROW_RUNTIME_ERROR(
hrStatus
, IDS_ERROR_CLUSDB_CREATE_HIVE
);
} // if: something went wrong.
TraceFuncExit();
} //*** CClusDB::CreateHive
//////////////////////////////////////////////////////////////////////////////
//++
//
// CClusDB::CleanupHive
//
// Description:
// Unload the cluster hive and delete the cluster database.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
// Exceptions Thrown:
// CRuntimeError
// If any of the APIs fail.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
CClusDB::CleanupHive( void )
{
TraceFunc( "" );
DWORD sc = ERROR_SUCCESS;
HKEY hTempKey;
// Check if the cluster hive is loaded before attempting to unload it.
if ( RegOpenKeyExW(
HKEY_LOCAL_MACHINE
, CLUSREG_KEYNAME_CLUSTER
, 0
, KEY_READ
, &hTempKey
)
== ERROR_SUCCESS
)
{
RegCloseKey( hTempKey );
//
// Enable the SE_RESTORE_PRIVILEGE.
//
// What we are doing here is that we are creating an object of
// type CEnableThreadPrivilege. This object enables the privilege
// in the constructor and restores it to its original state in the destructor.
//
CEnableThreadPrivilege etpAcquireRestorePrivilege( SE_RESTORE_NAME );
//
// Unload the cluster hive, so that it can be deleted. Note, thread must
// have SE_RESTORE_PRIVILEGE enabled.
//
sc = RegUnLoadKey(
HKEY_LOCAL_MACHINE
, CLUSREG_KEYNAME_CLUSTER
);
// MUSTDO: Check if ERROR_FILE_NOT_FOUND is an acceptable return value.
if ( sc != ERROR_SUCCESS )
{
LogMsg( "[BC] Error %#08x occurred while trying to unload the cluster hive.", sc );
goto Cleanup;
} // if: the hive could not be unloaded.
LogMsg( "[BC] The cluster hive has been unloaded." );
} // if: the cluster hive is loaded
else
{
LogMsg( "[BC] The cluster hive was not loaded." );
} // else: the cluster hive is not loaded
//
// Process ClusDB cleanup section in the INF file.
// This will delete the cluster database file and the log file.
//
if ( SetupInstallFromInfSection(
NULL // optional, handle of a parent window
, m_pbcaParentAction->HGetMainInfFileHandle() // handle to the INF file
, CLUSDB_CLEANUP_INF_SECTION_NAME // name of the Install section
, SPINST_FILES // which lines to install from section
, NULL // optional, key for registry installs
, NULL // optional, path for source files
, 0 // optional, specifies copy behavior
, g_GenericSetupQueueCallback // optional, specifies callback routine
, NULL // optional, callback routine context
, NULL // optional, device information set
, NULL // optional, device info structure
) == FALSE
)
{
sc = GetLastError();
LogMsg( "[BC] Error %#08x returned from SetupInstallFromInfSection() while trying to clean up the cluster database files.", sc );
goto Cleanup;
} // if: SetupInstallServicesFromInfSection failed
LogMsg( "[BC] The cluster database files have been cleaned up." );
Cleanup:
if ( sc != ERROR_SUCCESS )
{
LogMsg( "[BC] Error %#08x occurred while trying to cleanup the cluster database. Throwing an exception.", sc );
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_CLUSDB_CLEANUP );
}
TraceFuncExit();
} //*** CClusDB::CleanupHive