474 lines
17 KiB
C++
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()
|