////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1999-2000 Microsoft Corporation // // Module Name: // CClusDB.cpp // // Description: // Contains the definition of the CClusDB class. // // Maintained By: // Vij Vasu (Vvasu) 08-MAR-2000 // ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // Include Files ////////////////////////////////////////////////////////////////////////////// // The precompiled header. #include "pch.h" // For setupapi functions #include // 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 ClRtlSetObjSecurityInfo() and other functions. #include "clusrtl.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 ) { BCATraceScope( "" ); if ( m_pbcaParentAction == NULL) { BCATraceMsg( "Pointers to the parent action is NULL. Throwing exception." ); THROW_ASSERT( E_INVALIDARG , "CClusDB::CClusDB() => Required input pointer in NULL" ); } // if: the parent action pointer is NULL } //*** 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 ) { BCATraceScope( "" ); } //*** CClusDB::~CClusDB() ////////////////////////////////////////////////////////////////////////////// //++ // // void // 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 ) { BCATraceScope( "" ); LogMsg( "Attempting to create the cluster hive in the registry." ); OBJECT_ATTRIBUTES oaClusterHiveKey; OBJECT_ATTRIBUTES oaClusterHiveFile; HRESULT hrStatus = STATUS_SUCCESS; do { CStr strClusterHiveFileName( pbcaClusterActionIn->RStrGetClusterInstallDirectory() ); UNICODE_STRING ustrClusterHiveFileName; UNICODE_STRING ustrClusterHiveKeyName; strClusterHiveFileName += L"\\" CLUSTER_DATABASE_NAME; BCATraceMsg1( "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 ) { BCATraceMsg1( "RtlDosPathNameToNtPathName failed. Making up error code %#08x.", STATUS_OBJECT_PATH_INVALID ); // Use the most appropriate error code. hrStatus = STATUS_OBJECT_PATH_INVALID; break; } // 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 ) ) { BCATraceMsg1( "NtLoadKey2 returned error code %#08x.", hrStatus ); break; } // if: something went wrong with NtLoadKey2 BCATraceMsg( "NtLoadKey2 was successful." ); // Set the security descriptor on the hive. { DWORD dwError; // Open the cluster hive key. CRegistryKey rkClusterHive( HKEY_LOCAL_MACHINE, CLUSREG_KEYNAME_CLUSTER, KEY_ALL_ACCESS ); dwError = TW32( ClRtlSetObjSecurityInfo( rkClusterHive.HGetKey() , SE_REGISTRY_KEY , KEY_ALL_ACCESS , KEY_ALL_ACCESS , KEY_READ ) ); if ( dwError != ERROR_SUCCESS ) { hrStatus = HRESULT_FROM_WIN32( dwError ); BCATraceMsg1( "Error %#08x occurred trying set the cluster hive security.", hrStatus ); break; } // if: ClRtlSetObjSecurityInfo failed // Flush the changes to the registry. RegFlushKey( rkClusterHive.HGetKey() ); } // At this point, the cluster hive has been created. LogMsg( "The cluster hive has been created." ); } while( false ); // dummy do-while loop to avoid gotos. if ( NT_ERROR( hrStatus ) ) { LogMsg( "Error %#08x occurred trying to create the cluster hive.", hrStatus ); BCATraceMsg1( "Error %#08x occurred trying to create the cluster hive. Throwing exception.", hrStatus ); THROW_RUNTIME_ERROR( hrStatus , IDS_ERROR_CLUSDB_CREATE_HIVE ); } // if: something went wrong. } //*** CClusDB::CreateHive() ////////////////////////////////////////////////////////////////////////////// //++ // // void // 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 ) { BCATraceScope( "" ); DWORD dwError = ERROR_SUCCESS; do { HKEY hTempKey; // Check if the cluster hive is loaded before attempting to unload it. if ( RegOpenKeyEx( 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. // dwError = RegUnLoadKey( HKEY_LOCAL_MACHINE , CLUSREG_KEYNAME_CLUSTER ); // MUSTDO: Check if ERROR_FILE_NOT_FOUND is an acceptable return value. if ( dwError != ERROR_SUCCESS ) { LogMsg( "Error %#08x occurred while trying to unload the cluster hive.", dwError ); BCATraceMsg( "RegUnLoadKey returned an error while trying to unload the cluster hive." ); break; } // if: the hive could not be unloaded. BCATraceMsg( "The cluster hive has been unloaded." ); LogMsg( "The cluster hive has been unloaded." ); } // if: the cluster hive is loaded else { LogMsg( "The cluster hive was not loaded." ); BCATraceMsg( "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 ) { dwError = GetLastError(); LogMsg( "Error %#08x occurred while trying to clean up the cluster database files.", dwError ); BCATraceMsg( "Setup API returned an error while trying to cleanup the cluster database." ); break; } // if: SetupInstallServicesFromInfSection failed LogMsg( "The cluster database files have been cleaned up." ); } while( false ); // dummy do-while loop to avoid gotos if ( dwError != ERROR_SUCCESS ) { LogMsg( "Error %#08x occurred while trying to cleanup the cluster database.", dwError ); BCATraceMsg1( "Error %#08x occurred while trying to cleanup the cluster database. Throwing exception.", dwError ); THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( dwError ), IDS_ERROR_CLUSDB_CLEANUP ); } } //*** CClusDB::CleanupHive()