windows-nt/Source/XPSP1/NT/base/cluster/mgmt/clusocm/ctaskupgradent4.cpp
2020-09-26 16:20:57 +08:00

474 lines
17 KiB
C++

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000 Microsoft Corporation
//
// Module Name:
// CTaskUpgradeNT4.cpp
//
// Description:
// Implementation file for the CTaskUpgradeNT4 class.
//
// Header File:
// CTaskUpgradeNT4.h
//
// Maintained By:
// Vij Vasu (Vvasu) 18-APR-2000
// Created this file.
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Include Files
//////////////////////////////////////////////////////////////////////////////
// Precompiled header for this DLL.
#include "pch.h"
// The header file for this module.
#include "CTaskUpgradeNT4.h"
//////////////////////////////////////////////////////////////////////////////
// Macro Definitions
//////////////////////////////////////////////////////////////////////////////
// Needed for tracing.
DEFINE_THISCLASS( "CTaskUpgradeNT4" )
// Name of the cluster service executable
#define CLUSSVC_EXECUTABLE_NAME L"ClusSvc.exe"
// Multi-sz string of cluster service dependencies
#define CLUSSVC_DEPENDENCY_MULTISZ L"ClusNet\0RpcSs\0W32Time\0NetMan"
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskUpgradeNT4::CTaskUpgradeNT4
//
// Description:
// Constructor of the CTaskUpgradeNT4 class.
//
// Arguments:
// const CClusOCMApp & rAppIn
// Reference to the CClusOCMApp object that is hosting this task.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTaskUpgradeNT4::CTaskUpgradeNT4( const CClusOCMApp & rAppIn )
: BaseClass( rAppIn )
{
TraceFunc( "" );
TraceFuncExit();
} //*** CTaskUpgradeNT4::CTaskUpgradeNT4()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskUpgradeNT4::~CTaskUpgradeNT4
//
// Description:
// Destructor of the CTaskUpgradeNT4 class.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTaskUpgradeNT4::~CTaskUpgradeNT4( void )
{
TraceFunc( "" );
TraceFuncExit();
} //*** CTaskUpgradeNT4::~CTaskUpgradeNT4()
/////////////////////////////////////////////////////////////////////////////
//++
//
// DWORD
// CTaskUpgradeNT4::DwOcQueueFileOps
//
// Description:
// This function handles the OC_QUEUE_FILE_OPS messages from the Optional
// Components Manager. It installs the files needed for an upgrade from
// Windows 2000.
//
// Arguments:
// HSPFILEQ hSetupFileQueueIn
// Handle to the file queue to operate upon.
//
// Return Value:
// NO_ERROR if all went well.
// Other Win32 error codes on failure.
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD
CTaskUpgradeNT4::DwOcQueueFileOps( HSPFILEQ hSetupFileQueueIn )
{
TraceFunc( "" );
LogMsg( "Entering " __FUNCTION__ "()" );
DWORD dwReturnValue = NO_ERROR;
// The base class helper function does everything that we need to do here.
// So, just call it.
dwReturnValue = TW32( BaseClass::DwOcQueueFileOps( hSetupFileQueueIn, INF_SECTION_NT4_UPGRADE ) );
TraceFlow1( "Return Value is %#x.", dwReturnValue );
LogMsg( "Return Value is %#x.", dwReturnValue );
RETURN( dwReturnValue );
} //*** CTaskUpgradeNT4::DwOcQueueFileOps()
/////////////////////////////////////////////////////////////////////////////
//++
//
// DWORD
// CTaskUpgradeNT4::DwOcCompleteInstallation
//
// Description:
// This function handles the OC_COMPLETE_INSTALLATION messages from the
// Optional Components Manager during an upgrade from Windows 2000.
//
// Registry operations, COM component registrations, creation of servies
// etc. are performed in this function.
//
// Arguments:
// None.
//
// Return Value:
// NO_ERROR if all went well.
// Other Win32 error codes on failure.
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD
CTaskUpgradeNT4::DwOcCompleteInstallation( void )
{
TraceFunc( "" );
LogMsg( "Entering " __FUNCTION__ "()" );
DWORD dwReturnValue = NO_ERROR;
// Call the base class helper function to perform some registry and service
// related configuration from the INF file.
dwReturnValue = TW32( BaseClass::DwOcCompleteInstallation( INF_SECTION_NT4_UPGRADE ) );
//
// Change the cluster service display name, description, dependencies, failure actions
// and executable name.
//
while( dwReturnValue == NO_ERROR )
{
// Pointer the the cluster service directory.
const WCHAR * pcszInstallDir = NULL;
// Smart pointer to the cluster service display name string.
SmartSz sszClusSvcDispName;
// Smart pointer to the cluster service description string.
SmartSz sszClusSvcDesc;
// Smart pointer to the cluster service binary path string.
SmartSz sszClusSvcBinPath;
// Smart pointer to the cluster service.
SmartServiceHandle shClusSvc;
// Connect to the Service Control Manager
SmartServiceHandle shServiceMgr( OpenSCManager( NULL, NULL, GENERIC_READ | GENERIC_WRITE ) );
if ( shServiceMgr.HHandle() == NULL )
{
dwReturnValue = TW32( GetLastError() );
TraceFlow1( "Error %#x occurred trying to open a connection to the local service control manager.", dwReturnValue );
LogMsg( "Error %#x occurred trying to open a connection to the local service control manager.", dwReturnValue );
break;
} // if: opening the SCM was unsuccessful
TraceFlow( "Opened a handle to the service control manager." );
// Open a handle to the Cluster Service.
shClusSvc.Assign( OpenService( shServiceMgr, L"ClusSvc", SERVICE_ALL_ACCESS ) );
if ( shClusSvc.HHandle() == NULL )
{
dwReturnValue = TW32( GetLastError() );
TraceFlow1( "Error %#x occurred trying to open a handle to the cluster service.", dwReturnValue );
LogMsg( "Error %#x occurred trying to open a handle to the cluster service.", dwReturnValue );
break;
} // if: the handle could not be opened
TraceFlow( "Opened a handle to the cluster service." );
// Load the cluster service name string.
dwReturnValue = DwLoadString( IDS_CLUSSVC_DISPLAY_NAME, sszClusSvcDispName );
if ( dwReturnValue != ERROR_SUCCESS )
{
TraceFlow1( "Error %#x occurred trying load the display name of the cluster service.", dwReturnValue );
LogMsg( "Error %#x occurred trying load the display name of the cluster service.", dwReturnValue );
break;
} // if: we could not load the cluster service display name string
TraceFlow1( "The new cluster service display name is '%s'.", sszClusSvcDispName.PMem() );
// Load the cluster service description string.
dwReturnValue = DwLoadString( IDS_CLUSSVC_SERVICE_DESC, sszClusSvcDesc );
if ( dwReturnValue != ERROR_SUCCESS )
{
TraceFlow1( "Error %#x occurred trying load the description of the cluster service.", dwReturnValue );
LogMsg( "Error %#x occurred trying load the description of the cluster service.", dwReturnValue );
break;
} // if: we could not load the cluster service description string
TraceFlow1( "The new cluster service description is '%s'.", sszClusSvcDesc.PMem() );
//
// Form the service binary path by appending the name of the cluster service executable to
// the cluster service directory.
//
// Do not free the pointer returned by this call.
dwReturnValue = TW32( DwGetClusterServiceDirectory( pcszInstallDir ) );
if ( dwReturnValue != NO_ERROR )
{
TraceFlow1( "Error %#x occurred trying to determine the directory in which the cluster binaries are installed.", dwReturnValue );
LogMsg( "Error %#x occurred trying to determine the directory in which the cluster binaries are installed.", dwReturnValue );
break;
} // if: we could not get the cluster service installation directory
TraceFlow1( "The cluster service directory is '%ws'.", pcszInstallDir );
{
WCHAR * pszTempPtr;
// Length of the the install directory string, not including the terminating L'\0'
size_t cchInstallDirLen = wcslen( pcszInstallDir );
// Length of the cluster service executable name, including the terminating L'\0'
size_t cchClusSvcExeLen = sizeof( CLUSSVC_EXECUTABLE_NAME ) / sizeof( WCHAR );
// Allocate memory for the cluster service binary path (the extra character is for the intervening L'\\'.
sszClusSvcBinPath.Assign( new WCHAR[ cchInstallDirLen + 1 + cchClusSvcExeLen ] );
if ( sszClusSvcBinPath.FIsEmpty() )
{
dwReturnValue = TW32( ERROR_NOT_ENOUGH_MEMORY );
TraceFlow( "An error occurred trying to allocate memory for the cluster service binary path." );
LogMsg( "An error occurred trying to allocate memory for the cluster service binary path." );
break;
} // if: an error occurred trying to allocate memory for the cluster service binary path
pszTempPtr = sszClusSvcBinPath.PMem();
// Copy the install directory string to the newly allocated buffer.
wcsncpy( pszTempPtr, pcszInstallDir, cchInstallDirLen );
pszTempPtr += cchInstallDirLen;
// Copy the trailing L'\\' character
*pszTempPtr = L'\\';
++pszTempPtr;
// Copy the cluster service executable name.
wcsncpy( pszTempPtr, CLUSSVC_EXECUTABLE_NAME, cchClusSvcExeLen );
TraceFlow1( "The new cluster service binary path is '%s'.", sszClusSvcBinPath.PMem() );
}
// Change the binary path, dependency list and display name.
if ( ChangeServiceConfig(
shClusSvc.HHandle() // handle to service
, SERVICE_NO_CHANGE // type of service
, SERVICE_NO_CHANGE // when to start service
, SERVICE_NO_CHANGE // severity of start failure
, sszClusSvcBinPath.PMem() // service binary file name
, NULL // load ordering group name
, NULL // tag identifier
, CLUSSVC_DEPENDENCY_MULTISZ // array of dependency names
, NULL // account name
, NULL // account password
, sszClusSvcDispName.PMem() // display name
)
== FALSE
)
{
dwReturnValue = TW32( GetLastError() );
TraceFlow1( "Error %#x occurred trying to change the cluster service configuration.", dwReturnValue );
LogMsg( "Error %#x occurred trying to change the cluster service configuration.", dwReturnValue );
break;
} // if: ChangeServiceConfig() failed
TraceFlow( "The cluster service binary path, dependency list and display name have been changed." );
// Change the service description
{
SERVICE_DESCRIPTION sdServiceDescription;
sdServiceDescription.lpDescription = sszClusSvcDesc.PMem();
if ( ChangeServiceConfig2(
shClusSvc.HHandle() // handle to service
, SERVICE_CONFIG_DESCRIPTION // information level
, &sdServiceDescription // new data
)
== FALSE
)
{
dwReturnValue = TW32( GetLastError() );
TraceFlow1( "Error %#x occurred trying to change the cluster service description.", dwReturnValue );
LogMsg( "Error %#x occurred trying to change the cluster service description.", dwReturnValue );
break;
} // if: ChangeServiceConfig2() failed
}
TraceFlow( "The cluster service description has been changed." );
// Change the cluster service failure actions.
dwReturnValue = TW32( ClRtlSetSCMFailureActions( NULL ) );
if ( dwReturnValue != ERROR_SUCCESS )
{
TraceFlow1( "Error %#x occurred trying to set the cluster service failure actions.", dwReturnValue );
LogMsg( "Error %#x occurred trying to set the cluster service failure actions.", dwReturnValue );
break;
} // if: ClRtlSetSCMFailureActions() failed
TraceFlow( "The cluster service failure actions have been changed." );
LogMsg( "The cluster service configuration has been changed." );
break;
} // while: the call to the base class function has succeeded
TraceFlow1( "Return Value is %#x.", dwReturnValue );
LogMsg( "Return Value is %#x.", dwReturnValue );
RETURN( dwReturnValue );
} //*** CTaskUpgradeNT4::DwOcCompleteInstallation()
/////////////////////////////////////////////////////////////////////////////
//++
//
// DWORD
// CTaskUpgradeNT4::DwOcCleanup
//
// Description:
// This function handles the OC_CLEANUP messages from the
// Optional Components Manager during an upgrade from Windows 2000.
//
// If an error has previously occurred during this task, cleanup operations
// are performed. Otherwise nothing is done by this function.
//
// Arguments:
// None.
//
// Return Value:
// NO_ERROR if all went well.
// Other Win32 error codes on failure.
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD
CTaskUpgradeNT4::DwOcCleanup( void )
{
TraceFunc( "" );
LogMsg( "Entering " __FUNCTION__ "()" );
DWORD dwReturnValue = NO_ERROR;
// The base class helper function does everything that we need to do here.
// So, just call it.
dwReturnValue = TW32( BaseClass::DwOcCleanup( INF_SECTION_NT4_UPGRADE_CLEANUP ) );
TraceFlow1( "Return Value is %#x.", dwReturnValue );
LogMsg( "Return Value is %#x.", dwReturnValue );
RETURN( dwReturnValue );
} //*** CTaskUpgradeNT4::DwOcCleanup()
/////////////////////////////////////////////////////////////////////////////
//++
//
// DWORD
// CTaskUpgradeNT4::DwSetDirectoryIds
//
// Description:
// This function maps ids specified in the INF file to directories.
// The cluster installation directory is got from the service control
// manager, since it is possible the the cluster binaries are installed
// in a non-default location.
//
// Arguments:
// None.
//
// Return Value:
// NO_ERROR if all went well.
// Other Win32 error codes on failure.
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD
CTaskUpgradeNT4::DwSetDirectoryIds()
{
TraceFunc( "" );
LogMsg( "Entering " __FUNCTION__ "()" );
DWORD dwReturnValue = NO_ERROR;
do
{
const WCHAR * pcszInstallDir = NULL;
// If we are here, the this node is already a part of a cluster. So, get the
// installation directory from SCM.
TraceFlow( "This node is part of a cluster. Trying to determine the installation directory." );
LogMsg( "This node is part of a cluster. Trying to determine the installation directory." );
// Do not free the pointer returned by this call.
dwReturnValue = TW32( DwGetClusterServiceDirectory( pcszInstallDir ) );
if ( dwReturnValue != NO_ERROR )
{
TraceFlow1( "Error %#x occurred trying to determine the directory in which the cluster binaries are installed.", dwReturnValue );
LogMsg( "Error %#x occurred trying to determine the directory in which the cluster binaries are installed.", dwReturnValue );
break;
} // if: we could not get the cluster service installation directory
TraceFlow1( "The cluster binaries are installed in the directory '%ws'.", pcszInstallDir );
LogMsg( "The cluster binaries are installed in the directory '%ws'.", pcszInstallDir );
// Create the mapping between the directory id and the path
if ( SetupSetDirectoryId(
RGetApp().RsicGetSetupInitComponent().ComponentInfHandle
, CLUSTER_DEFAULT_INSTALL_DIRID
, pcszInstallDir
)
== FALSE
)
{
dwReturnValue = TW32( GetLastError() );
TraceFlow1( "Error %#x occurred trying set the cluster install directory id.", dwReturnValue );
LogMsg( "Error %#x occurred trying set the cluster install directory id.", dwReturnValue );
break;
} // if: SetupSetDirectoryId() failed
TraceFlow2( "The id %d maps to '%ws'.", CLUSTER_DEFAULT_INSTALL_DIRID, pcszInstallDir );
LogMsg( "The id %d maps to '%ws'.", CLUSTER_DEFAULT_INSTALL_DIRID, pcszInstallDir );
}
while ( false ); // dummy do-while loop to avoid gotos
TraceFlow1( "Return Value is %#x.", dwReturnValue );
LogMsg( "Return Value is %#x.", dwReturnValue );
RETURN( dwReturnValue );
} //*** CTaskUpgradeNT4::DwSetDirectoryIds()