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.
898 lines
29 KiB
898 lines
29 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1999-2002 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// CClusDisk.cpp
|
|
//
|
|
// Description:
|
|
// Contains the definition of the CClusDisk class.
|
|
//
|
|
// Maintained By:
|
|
// David Potter (DavidP) 15-JUN-2001
|
|
// Vij Vasu (Vvasu) 08-MAR-2000
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Include Files
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The precompiled header.
|
|
#include "Pch.h"
|
|
|
|
// The header for this file
|
|
#include "CClusDisk.h"
|
|
|
|
// Required by clusdisk.h
|
|
#include <ntddscsi.h>
|
|
|
|
// For IOCTL_DISK_CLUSTER_ATTACH and IOCTL_DISK_CLUSTER_DETACH
|
|
#include <clusdisk.h>
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Macros
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The name of the ClusDisk service
|
|
#define CLUSDISK_SERVICE_NAME L"ClusDisk"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDisk::CClusDisk
|
|
//
|
|
// Description:
|
|
// Constructor of the CClusDisk class. Opens a handle to the service.
|
|
//
|
|
// 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.
|
|
//
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any exceptions thrown by underlying functions
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CClusDisk::CClusDisk(
|
|
CBaseClusterAction * pbcaParentActionIn
|
|
)
|
|
: m_cservClusDisk( CLUSDISK_SERVICE_NAME )
|
|
, m_pbcaParentAction( pbcaParentActionIn )
|
|
{
|
|
|
|
TraceFunc( "" );
|
|
|
|
if ( m_pbcaParentAction == NULL)
|
|
{
|
|
LogMsg( "[BC] Pointers to the parent action is NULL. Throwing an exception." );
|
|
THROW_ASSERT(
|
|
E_INVALIDARG
|
|
, "CClusDisk::CClusDisk() => Required input pointer in NULL"
|
|
);
|
|
} // if: the parent action pointer is NULL
|
|
|
|
//
|
|
// The ClusDisk service has been created at the time the cluster binaries were
|
|
// installed. So, get a handle to the ClusDisk service.
|
|
//
|
|
|
|
SmartSCMHandle sscmhTempHandle(
|
|
OpenService(
|
|
pbcaParentActionIn->HGetSCMHandle()
|
|
, CLUSDISK_SERVICE_NAME
|
|
, SERVICE_ALL_ACCESS
|
|
)
|
|
);
|
|
|
|
// Did we get a handle to the service?
|
|
if ( sscmhTempHandle.FIsInvalid() )
|
|
{
|
|
DWORD sc = TW32( GetLastError() );
|
|
|
|
LogMsg( "[BC] Error %#08x occurred trying to open a handle to the ClusDisk service. Throwing an exception.", sc );
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_CLUSDISK_OPEN );
|
|
} // if: OpenService failed
|
|
|
|
// Initialize the member variable.
|
|
m_sscmhServiceHandle = sscmhTempHandle;
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDisk::CClusDisk
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDisk::~CClusDisk
|
|
//
|
|
// Description:
|
|
// Destructor of the CClusDisk class.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by underlying functions
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CClusDisk::~CClusDisk( void )
|
|
{
|
|
TraceFunc( "" );
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDisk::~CClusDisk
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDisk::ConfigureService
|
|
//
|
|
// Description:
|
|
// This function enables and starts the ClusDisk service.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDisk::ConfigureService( void )
|
|
{
|
|
TraceFunc( "" );
|
|
LogMsg( "[BC] Configuring the ClusDisk service." );
|
|
|
|
bool fIsRunning;
|
|
|
|
{
|
|
CStatusReport srConfigClusDisk(
|
|
PbcaGetParent()->PBcaiGetInterfacePointer()
|
|
, TASKID_Major_Configure_Cluster_Services
|
|
, TASKID_Minor_Configuring_ClusDisk_Service
|
|
, 0, 1
|
|
, IDS_TASK_CONFIG_CLUSDISK
|
|
);
|
|
|
|
// Send the next step of this status report.
|
|
srConfigClusDisk.SendNextStep( S_OK );
|
|
|
|
//
|
|
// First, initialize the ClusDisk service to make sure that it does not retain
|
|
// any state from another cluster that this node may have been a part of.
|
|
//
|
|
fIsRunning = FInitializeState();
|
|
|
|
//
|
|
// Enable the service.
|
|
//
|
|
if ( ChangeServiceConfig(
|
|
m_sscmhServiceHandle.HHandle() // handle to service
|
|
, SERVICE_NO_CHANGE // type of service
|
|
, SERVICE_SYSTEM_START // when to start service
|
|
, SERVICE_NO_CHANGE // severity of start failure
|
|
, NULL // service binary file name
|
|
, NULL // load ordering group name
|
|
, NULL // tag identifier
|
|
, NULL // array of dependency names
|
|
, NULL // account name
|
|
, NULL // account password
|
|
, NULL // display name
|
|
)
|
|
== FALSE
|
|
)
|
|
{
|
|
DWORD sc = TW32( GetLastError() );
|
|
|
|
LogMsg( "[BC] Could not enable the ClusDisk service. Error %#08x. Throwing an exception.", sc );
|
|
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_CLUSDISK_CONFIGURE );
|
|
} // if: we could not enable the service.
|
|
|
|
// Send the last step of this status report.
|
|
srConfigClusDisk.SendNextStep( S_OK );
|
|
}
|
|
|
|
LogMsg( "[BC] The ClusDisk service has been enabled." );
|
|
|
|
{
|
|
UINT cQueryCount = 10;
|
|
|
|
CStatusReport srStartClusDisk(
|
|
PbcaGetParent()->PBcaiGetInterfacePointer()
|
|
, TASKID_Major_Configure_Cluster_Services
|
|
, TASKID_Minor_Starting_ClusDisk_Service
|
|
, 1, cQueryCount + 2 // we will send at most cQueryCount reports while waiting for the service to start (the two extra sends are below)
|
|
, IDS_TASK_STARTING_CLUSDISK
|
|
);
|
|
|
|
// Send the next step of this status report.
|
|
srStartClusDisk.SendNextStep( S_OK );
|
|
|
|
// This call does not actually create the service - it creates the registry entries needed
|
|
// by ClusDisk.
|
|
m_cservClusDisk.Create( m_pbcaParentAction->HGetMainInfFileHandle() );
|
|
|
|
// If the service was not already running, start the service.
|
|
if ( ! fIsRunning )
|
|
{
|
|
m_cservClusDisk.Start(
|
|
m_pbcaParentAction->HGetSCMHandle()
|
|
, true // wait for the service to start
|
|
, 500 // wait 500ms between queries for status.
|
|
, cQueryCount // query cQueryCount times.
|
|
, &srStartClusDisk // status report to be sent while waiting for the service to start
|
|
);
|
|
} // if: ClusDisk was not already running.
|
|
else
|
|
{
|
|
// Nothing more need be done.
|
|
LogMsg( "[BC] ClusDisk is already running." );
|
|
} // else: ClusDisk is already running.
|
|
|
|
LogMsg( "[BC] The ClusDisk service has been successfully configured and started." );
|
|
|
|
// Send the last step of this status report.
|
|
srStartClusDisk.SendLastStep( S_OK );
|
|
}
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDisk::ConfigureService
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDisk::CleanupService
|
|
//
|
|
// Description:
|
|
// This function enables and starts the ClusDisk service.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDisk::CleanupService( void )
|
|
{
|
|
TraceFunc( "" );
|
|
LogMsg( "[BC] Cleaning up the ClusDisk service." );
|
|
|
|
//
|
|
// First, initialize the ClusDisk service to make sure that it does not retain
|
|
// any state from this cluster.
|
|
//
|
|
FInitializeState();
|
|
|
|
//
|
|
// Disable the service.
|
|
//
|
|
if ( ChangeServiceConfig(
|
|
m_sscmhServiceHandle.HHandle() // handle to service
|
|
, SERVICE_NO_CHANGE // type of service
|
|
, SERVICE_DISABLED // when to start service
|
|
, SERVICE_NO_CHANGE // severity of start failure
|
|
, NULL // service binary file name
|
|
, NULL // load ordering group name
|
|
, NULL // tag identifier
|
|
, NULL // array of dependency names
|
|
, NULL // account name
|
|
, NULL // account password
|
|
, NULL // display name
|
|
)
|
|
== FALSE
|
|
)
|
|
{
|
|
DWORD sc = TW32( GetLastError() );
|
|
|
|
LogMsg( "[BC] Could not disable the ClusDisk service. Error %#08x. Throwing an exception.", sc );
|
|
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_CLUSDISK_CLEANUP );
|
|
} // if: we could not enable the service.
|
|
|
|
LogMsg( "[BC] The ClusDisk service has been successfully cleaned up and disabled." );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDisk::CleanupService
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDisk::FInitializeState
|
|
//
|
|
// Description:
|
|
// This function initializes the ClusDisk service and brings it back to
|
|
// its ground state.
|
|
//
|
|
// If the service is running, then ClusDisk is asked to detach
|
|
// itself from all the disks that it is currently attached to.
|
|
//
|
|
// If the service is not running, then its parameters key is deleted
|
|
// so as to prevent ClusDisk from reusing any keys leftover from a previous
|
|
// cluster.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// Returns true is the service was running before the initialization began.
|
|
// Returns false if it was not.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
bool
|
|
CClusDisk::FInitializeState( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LogMsg( "[BC] Initializing ClusDisk service state.");
|
|
|
|
bool fIsRunning = false; // Initially set to false: ClusDisk is not running, true: ClusDisk is running.
|
|
DWORD sc = ERROR_SUCCESS;
|
|
|
|
SERVICE_STATUS ssStatus;
|
|
|
|
//
|
|
// Check if the service is running.
|
|
//
|
|
ZeroMemory( &ssStatus, sizeof( ssStatus ) );
|
|
|
|
// Query the service for its status.
|
|
if ( QueryServiceStatus(
|
|
m_sscmhServiceHandle.HHandle()
|
|
, &ssStatus
|
|
)
|
|
== 0
|
|
)
|
|
{
|
|
sc = TW32( GetLastError() );
|
|
LogMsg( "Error %#08x occurred while trying to query ClusDisk status. Throwing an exception.", sc );
|
|
|
|
goto Cleanup;
|
|
} // if: we could not query the service for its status.
|
|
|
|
if ( ssStatus.dwCurrentState == SERVICE_RUNNING )
|
|
{
|
|
LogMsg( "[BC] The ClusDisk service is already running. It will be detached from all disks." );
|
|
|
|
// ClusDisk is running.
|
|
fIsRunning = true;
|
|
|
|
// Make sure that it is not attached to any disks already.
|
|
DetachFromAllDisks();
|
|
} // if: the service is running.
|
|
else
|
|
{
|
|
if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
|
|
{
|
|
LogMsg( "[BC] The ClusDisk service is not running. Its registry will be cleaned up." );
|
|
|
|
// Call the cleanup routine of the embedded service object.
|
|
m_cservClusDisk.Cleanup( m_pbcaParentAction->HGetMainInfFileHandle() );
|
|
} // if: the service is stopped
|
|
else
|
|
{
|
|
sc = TW32( ERROR_INVALID_HANDLE_STATE );
|
|
LogMsg( "[BC] ClusDisk is in an incorrect state (%#08x).", ssStatus.dwCurrentState );
|
|
goto Cleanup;
|
|
} // else: the service is in some other state.
|
|
} // else: ClusDisk is not running.
|
|
|
|
Cleanup:
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC] Error %#08x occurred trying initialize the ClusDisk service state. Throwing an exception.", sc );
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_CLUSDISK_INITIALIZE );
|
|
} // if: something has gone wrong
|
|
|
|
LogMsg( "[BC] The ClusDisk service state has been successfully initialized.");
|
|
|
|
RETURN( fIsRunning );
|
|
|
|
} //*** CClusDisk::FInitializeState
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDisk::DetachFromAllDisks
|
|
//
|
|
// Description:
|
|
// This function detaches ClusDisk from all the disks that it is currently
|
|
// attached to. A prerequisite for calling this function is that the
|
|
// ClusDisk service is running.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDisk::DetachFromAllDisks( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LONG lError = ERROR_SUCCESS;
|
|
|
|
LogMsg( "[BC] Detaching the ClusDisk service from all disks." );
|
|
|
|
do
|
|
{
|
|
CRegistryKey rkSignaturesKey;
|
|
DWORD dwSignatureCount = 0;
|
|
DWORD dwMaxSignatureNameLen = 0;
|
|
DWORD dwSignatureIndex = 0;
|
|
|
|
// Try and open the ClusDisk signatures key.
|
|
try
|
|
{
|
|
rkSignaturesKey.OpenKey(
|
|
HKEY_LOCAL_MACHINE
|
|
, L"System\\CurrentControlSet\\Services\\ClusDisk\\Parameters\\Signatures"
|
|
, KEY_ALL_ACCESS
|
|
);
|
|
} // try: to open the ClusDisk signatures key.
|
|
catch( CRuntimeError & rteException )
|
|
{
|
|
//
|
|
// If we are here, then OpenKey threw a CRuntimeError.Check if the
|
|
// error was ERROR_FILE_NOT_FOUND. This means that the key does
|
|
// not exist and we are done.
|
|
//
|
|
// Otherwise, some other error ocurred, so rethrow the exception.
|
|
//
|
|
|
|
if ( rteException.HrGetErrorCode() == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
// There is nothing else to do.
|
|
break;
|
|
} // if: the ClusDisk parameters key does not exist.
|
|
|
|
// Some other error occurred.
|
|
throw;
|
|
} // catch( CRuntimeError & )
|
|
|
|
//
|
|
// Find out the number of signatures and the maximum length of the signature
|
|
// key names.
|
|
//
|
|
lError = TW32( RegQueryInfoKeyW(
|
|
rkSignaturesKey.HGetKey() // handle to key
|
|
, NULL // class buffer
|
|
, NULL // size of class buffer
|
|
, NULL // reserved
|
|
, &dwSignatureCount // number of subkeys
|
|
, &dwMaxSignatureNameLen // longest subkey name
|
|
, NULL // longest class string
|
|
, NULL // number of value entries
|
|
, NULL // longest value name
|
|
, NULL // longest value data
|
|
, NULL // descriptor length
|
|
, NULL // last write time
|
|
) );
|
|
|
|
if ( lError != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC] Error %#08x from RegQueryInfoKeyW() querying the number of signatures.", lError );
|
|
break;
|
|
} // if: RegQueryInfoKeyW() failed.
|
|
|
|
// Account for the terminating '\0'
|
|
++dwMaxSignatureNameLen;
|
|
|
|
// Allocate the memory required to hold the signatures.
|
|
CSmartGenericPtr< CArrayPtrTrait< DWORD > > rgdwSignatureArrayIn( new DWORD[ dwSignatureCount ] );
|
|
if ( rgdwSignatureArrayIn.FIsEmpty() )
|
|
{
|
|
lError = TW32( ERROR_OUTOFMEMORY );
|
|
LogMsg( "[BC] Erro allocating %d bytes required for the signature array.", dwSignatureCount );
|
|
break;
|
|
} // if:memory allocation failed.
|
|
|
|
// Allocate the memory required for the signature string.
|
|
SmartSz sszSignatureKeyName( new WCHAR[ dwMaxSignatureNameLen ] );
|
|
if ( sszSignatureKeyName.FIsEmpty() )
|
|
{
|
|
lError = TW32( ERROR_OUTOFMEMORY );
|
|
LogMsg( "[BC] Error allocating %d bytes required for the longest signature key name.", dwMaxSignatureNameLen );
|
|
break;
|
|
} // if:memory allocation failed.
|
|
|
|
|
|
//
|
|
// Iterate through the list of signatures that ClusDisk is currently attached
|
|
// to and add each of them to the array of signatures. We cannot detach as
|
|
// we enumerate since ClusDisk removes the signature key when it detaches from
|
|
// a disk and RegEnumKeyEx requires that the key being enumerated not change
|
|
// during an enumeration.
|
|
//
|
|
do
|
|
{
|
|
DWORD dwTempSize = dwMaxSignatureNameLen;
|
|
WCHAR * pwcCharPtr;
|
|
|
|
lError = RegEnumKeyExW(
|
|
rkSignaturesKey.HGetKey()
|
|
, dwSignatureIndex
|
|
, sszSignatureKeyName.PMem()
|
|
, &dwTempSize
|
|
, NULL
|
|
, NULL
|
|
, NULL
|
|
, NULL
|
|
);
|
|
|
|
if ( lError != ERROR_SUCCESS )
|
|
{
|
|
if ( lError == ERROR_NO_MORE_ITEMS )
|
|
{
|
|
lError = ERROR_SUCCESS;
|
|
} // if: we are at the end of the enumeration
|
|
else
|
|
{
|
|
TW32( lError );
|
|
LogMsg( "[BC] Error %#08x from RegEnumKeyEx(). Index = %d.", lError, dwSignatureIndex );
|
|
} // else: something else went wrong
|
|
|
|
break;
|
|
} // if: RegEnumKeyEx() did not succeed
|
|
|
|
LogMsg( "[BC] Signature %d is '%s'.", dwSignatureIndex + 1, sszSignatureKeyName.PMem() );
|
|
|
|
// Convert the key name to a hex number.
|
|
( rgdwSignatureArrayIn.PMem() )[ dwSignatureIndex ] =
|
|
wcstoul( sszSignatureKeyName.PMem(), &pwcCharPtr, 16 );
|
|
|
|
// Did the conversion succeed.
|
|
if ( sszSignatureKeyName.PMem() == pwcCharPtr )
|
|
{
|
|
lError = TW32( ERROR_INVALID_PARAMETER );
|
|
TraceFlow( "_wcstoul() failed." );
|
|
break;
|
|
} // if: the conversion of the signature string to a number failed.
|
|
|
|
// Increment the index.
|
|
++dwSignatureIndex;
|
|
}
|
|
while( true ); // loop infinitely
|
|
|
|
if ( lError != ERROR_SUCCESS )
|
|
{
|
|
break;
|
|
} // if: something went wrong
|
|
|
|
// Detach ClusDisks from all the disks we found it attached to.
|
|
DetachFromDisks(
|
|
rgdwSignatureArrayIn.PMem()
|
|
, dwSignatureCount
|
|
);
|
|
|
|
}
|
|
while( false ); // dummy do-while loop to avoid gotos.
|
|
|
|
if ( lError != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC] Error %#08x occurred trying detach ClusDisk from all the disks. Throwing an exception.", lError );
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( lError ), IDS_ERROR_CLUSDISK_INITIALIZE );
|
|
} // if: something has gone wrong
|
|
|
|
LogMsg( "[BC] The ClusDisk service has been successfully detached from all disks." );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDisk::DetachFromAllDisks
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDisk::DetachFromDisks
|
|
//
|
|
// Description:
|
|
// This function detaches ClusDisk from the disks specified
|
|
// by a list of signatures. A prerequisite for calling this function is
|
|
// that the ClusDisk service is running.
|
|
//
|
|
// Arguments:
|
|
// rgdwSignatureArrayIn
|
|
// Array of signatures of disks to detach from.
|
|
//
|
|
// uiArraySizeIn
|
|
// Number of signatures in above array.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDisk::DetachFromDisks(
|
|
DWORD rgdwSignatureArrayIn[]
|
|
, UINT uiArraySizeIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
UNICODE_STRING ustrClusDiskDeviceName;
|
|
OBJECT_ATTRIBUTES oaClusDiskAttrib;
|
|
HANDLE hClusDisk;
|
|
IO_STATUS_BLOCK iosbIoStatusBlock;
|
|
DWORD dwTempSize = 0;
|
|
|
|
LogMsg( "[BC] Trying to detach from %d disks.", uiArraySizeIn );
|
|
|
|
//
|
|
// If the list is empty then leave since there are no disks to detach
|
|
// from.
|
|
//
|
|
if ( ( uiArraySizeIn == 0 ) || ( rgdwSignatureArrayIn == NULL ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
// Initialize the unicode string with the name of the ClusDisk device.
|
|
RtlInitUnicodeString( &ustrClusDiskDeviceName, L"\\Device\\ClusDisk0" );
|
|
|
|
InitializeObjectAttributes(
|
|
&oaClusDiskAttrib
|
|
, &ustrClusDiskDeviceName
|
|
, OBJ_CASE_INSENSITIVE
|
|
, NULL
|
|
, NULL
|
|
);
|
|
|
|
LogMsg( "[BC] Trying to get a handle to the ClusDisk device." );
|
|
|
|
// Get a handle to the ClusDisk device.
|
|
ntStatus = THR( NtCreateFile(
|
|
&hClusDisk
|
|
, SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA
|
|
, &oaClusDiskAttrib
|
|
, &iosbIoStatusBlock
|
|
, NULL
|
|
, FILE_ATTRIBUTE_NORMAL
|
|
, FILE_SHARE_READ | FILE_SHARE_WRITE
|
|
, FILE_OPEN
|
|
, 0
|
|
, NULL
|
|
, 0
|
|
) );
|
|
if ( NT_SUCCESS( ntStatus ) == FALSE )
|
|
{
|
|
LogMsg( "[BC] Error %#08x trying to get a handle to the ClusDisk device.", ntStatus );
|
|
goto Cleanup;
|
|
} // if: NtCreateFile failed.
|
|
|
|
{ // new block so that that the file handle is closed.
|
|
// Assign the opened file handle to a smart handle for safe closing.
|
|
CSmartResource<
|
|
CHandleTrait<
|
|
HANDLE
|
|
, NTSTATUS
|
|
, NtClose
|
|
>
|
|
> snthClusDiskHandle( hClusDisk );
|
|
|
|
// Detach ClusDisk from this disk.
|
|
if ( DeviceIoControl(
|
|
hClusDisk
|
|
, IOCTL_DISK_CLUSTER_DETACH_LIST
|
|
, rgdwSignatureArrayIn
|
|
, uiArraySizeIn * sizeof( rgdwSignatureArrayIn[ 0 ] )
|
|
, NULL
|
|
, 0
|
|
, &dwTempSize
|
|
, FALSE
|
|
)
|
|
== FALSE
|
|
)
|
|
{
|
|
ntStatus = TW32( GetLastError() );
|
|
LogMsg( "[BC] Error %#08x from DeviceIoControl() getting signature list.", ntStatus );
|
|
ntStatus = HRESULT_FROM_WIN32( ntStatus );
|
|
} // if: DeviceIoControl() failed
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if ( ntStatus != STATUS_SUCCESS )
|
|
{
|
|
LogMsg( "[BC] Error %#08x occurred trying to detach ClusDisk from a disk. Throwing an exception.", ntStatus );
|
|
THROW_RUNTIME_ERROR( ntStatus, IDS_ERROR_CLUSDISK_INITIALIZE );
|
|
} // if: something has gone wrong
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDisk::DetachFromDisks
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDisk::AttachToDisks
|
|
//
|
|
// Description:
|
|
// This function attaches ClusDisk to the disks specified
|
|
// by a list of signatures. A prerequisite for calling this function is
|
|
// that the ClusDisk service is running.
|
|
//
|
|
// Arguments:
|
|
// rgdwSignatureArrayIn
|
|
// Array of signatures of disks to attach to.
|
|
//
|
|
// uiArraySizeIn
|
|
// Number of signatures in above array.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDisk::AttachToDisks(
|
|
DWORD rgdwSignatureArrayIn[]
|
|
, UINT uiArraySizeIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
UNICODE_STRING ustrClusDiskDeviceName;
|
|
OBJECT_ATTRIBUTES oaClusDiskAttrib;
|
|
HANDLE hClusDisk;
|
|
IO_STATUS_BLOCK iosbIoStatusBlock;
|
|
DWORD dwTempSize = 0;
|
|
|
|
LogMsg( "[BC] Trying to attach to %d disks.", uiArraySizeIn );
|
|
|
|
//
|
|
// If the list is empty then leave since there are no disks to attach
|
|
// to.
|
|
//
|
|
if ( ( uiArraySizeIn == 0 ) || ( rgdwSignatureArrayIn == NULL ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
// Initialize the unicode string with the name of the ClusDisk device.
|
|
RtlInitUnicodeString( &ustrClusDiskDeviceName, L"\\Device\\ClusDisk0" );
|
|
|
|
InitializeObjectAttributes(
|
|
&oaClusDiskAttrib
|
|
, &ustrClusDiskDeviceName
|
|
, OBJ_CASE_INSENSITIVE
|
|
, NULL
|
|
, NULL
|
|
);
|
|
|
|
LogMsg( "[BC] Trying to get a handle to the ClusDisk device." );
|
|
|
|
// Get a handle to the ClusDisk device.
|
|
ntStatus = THR( NtCreateFile(
|
|
&hClusDisk
|
|
, SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA
|
|
, &oaClusDiskAttrib
|
|
, &iosbIoStatusBlock
|
|
, NULL
|
|
, FILE_ATTRIBUTE_NORMAL
|
|
, FILE_SHARE_READ | FILE_SHARE_WRITE
|
|
, FILE_OPEN
|
|
, 0
|
|
, NULL
|
|
, 0
|
|
) );
|
|
if ( NT_SUCCESS( ntStatus ) == FALSE )
|
|
{
|
|
LogMsg( "[BC] Error %#08x trying to get a handle to the ClusDisk device.", ntStatus );
|
|
goto Cleanup;
|
|
} // if: NtCreateFile failed.
|
|
|
|
{ // new block so that that the file handle is closed.
|
|
// Assign the opened file handle to a smart handle for safe closing.
|
|
CSmartResource<
|
|
CHandleTrait<
|
|
HANDLE
|
|
, NTSTATUS
|
|
, NtClose
|
|
>
|
|
> snthClusDiskHandle( hClusDisk );
|
|
|
|
// Attach ClusDisk to this signature list.
|
|
if ( DeviceIoControl(
|
|
hClusDisk
|
|
, IOCTL_DISK_CLUSTER_ATTACH_LIST
|
|
, rgdwSignatureArrayIn
|
|
, uiArraySizeIn * sizeof( rgdwSignatureArrayIn[0] )
|
|
, NULL
|
|
, 0
|
|
, &dwTempSize
|
|
, FALSE
|
|
)
|
|
== FALSE
|
|
)
|
|
{
|
|
ntStatus = GetLastError();
|
|
LogMsg( "[BC] Error %#08x from DeviceIoControl() getting signature list.", ntStatus );
|
|
ntStatus = HRESULT_FROM_WIN32( TW32( ntStatus ) );
|
|
} // if: DeviceIoControl() failed
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if ( ntStatus != STATUS_SUCCESS )
|
|
{
|
|
LogMsg( "[BC] Error %#08x occurred trying attach ClusDisk to a disk. Throwing an exception.", ntStatus );
|
|
THROW_RUNTIME_ERROR( ntStatus, IDS_ERROR_CLUSDISK_INITIALIZE );
|
|
} // if: something has gone wrong
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDisk::AttachToDisks
|