|
|
/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1996-2000 Microsoft Corporation
//
// Module Name:
// Disks.cpp
//
// Abstract:
// Implementation of the CPhysDiskParamsPage class.
//
// Author:
// David Potter (davidp) June 28, 1996
//
// Revision History:
//
// Notes:
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CluAdmX.h"
#include "ExtObj.h"
#include "Disks.h"
#include "DDxDDv.h"
#include "PropList.h"
#include "HelpData.h"
#include "ExcOper.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
/////////////////////////////////////////////////////////////////////////////
// CPhysDiskParamsPage property page
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CPhysDiskParamsPage, CBasePropertyPage)
/////////////////////////////////////////////////////////////////////////////
// Message Maps
BEGIN_MESSAGE_MAP(CPhysDiskParamsPage, CBasePropertyPage) //{{AFX_MSG_MAP(CPhysDiskParamsPage)
ON_CBN_SELCHANGE(IDC_PP_DISKS_PARAMS_DISK, OnChangeDisk) //}}AFX_MSG_MAP
// TODO: Modify the following lines to represent the data displayed on this page.
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::CPhysDiskParamsPage
//
// Routine Description:
// Default constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CPhysDiskParamsPage::CPhysDiskParamsPage(void) : CBasePropertyPage(g_aHelpIDs_IDD_PP_DISKS_PARAMETERS, g_aHelpIDs_IDD_WIZ_DISKS_PARAMETERS) { // TODO: Modify the following lines to represent the data displayed on this page.
//{{AFX_DATA_INIT(CPhysDiskParamsPage)
m_strDisk = _T(""); //}}AFX_DATA_INIT
m_dwSignature = 0;
m_pbAvailDiskInfo = NULL; m_cbAvailDiskInfo = 0; m_pbDiskInfo = NULL; m_cbDiskInfo = 0;
// Setup the property array.
{ m_rgProps[epropSignature].Set(REGPARAM_DISKS_SIGNATURE, m_dwSignature, m_dwPrevSignature); } // Setup the property array
m_iddPropertyPage = IDD_PP_DISKS_PARAMETERS; m_iddWizardPage = IDD_WIZ_DISKS_PARAMETERS;
} //*** CPhysDiskParamsPage::CPhysDiskParamsPage()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::~CPhysDiskParamsPage
//
// Routine Description:
// Destructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CPhysDiskParamsPage::~CPhysDiskParamsPage(void) { delete [] m_pbAvailDiskInfo; delete [] m_pbDiskInfo;
} //*** CPhysDiskParamsPage::~CPhysDiskParamsPage()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::HrInit
//
// Routine Description:
// Initialize the page.
//
// Arguments:
// peo [IN OUT] Pointer to the extension object.
//
// Return Value:
// S_OK Page initialized successfully.
// hr Page failed to initialize.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CPhysDiskParamsPage::HrInit(IN OUT CExtObject * peo) { HRESULT _hr; CWaitCursor _wc;
do { // Call the base class method.
_hr = CBasePropertyPage::HrInit(peo); if ( FAILED( _hr ) ) { break; } // if: error from base class method
// Collect available disk information.
BGetAvailableDisks();
// If creating a new resource, select the first disk.
// Otherwise, collect information about the selected disk.
if (BWizard()) { CLUSPROP_BUFFER_HELPER buf;
buf.pb = m_pbAvailDiskInfo; if (m_cbAvailDiskInfo > 0) { while (buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) { if (BStringFromDiskInfo(buf, m_cbAvailDiskInfo, m_strDisk)) break; ASSERT( (buf.pSyntax->dw == CLUSPROP_SYNTAX_ENDMARK) || (buf.pSyntax->dw == CLUSPROP_SYNTAX_DISK_SIGNATURE)); } // while: more entries in the list
} // if: there are available disks
} // if: creating a new resource
else { // Don't return false because that will prevent the page from showing up.
BGetDiskInfo();
// Get the current state of the resource.
m_crs = GetClusterResourceState(Peo()->PrdResData()->m_hresource, NULL, NULL, NULL, NULL ); } // else: viewing an existing resource
} while ( 0 );
return _hr;
} //*** CPhysDiskParamsPage::HrInit()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::DoDataExchange
//
// Routine Description:
// Do data exchange between the dialog and the class.
//
// Arguments:
// pDX [IN OUT] Data exchange object
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CPhysDiskParamsPage::DoDataExchange(CDataExchange * pDX) { if (!pDX->m_bSaveAndValidate || !BSaved()) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: Modify the following lines to represent the data displayed on this page.
//{{AFX_DATA_MAP(CPhysDiskParamsPage)
DDX_Control(pDX, IDC_PP_DISKS_PARAMS_DISK, m_cboxDisk); DDX_Text(pDX, IDC_PP_DISKS_PARAMS_DISK, m_strDisk); //}}AFX_DATA_MAP
if (pDX->m_bSaveAndValidate) { if (!BBackPressed()) { if (BWizard() && !( (m_strDisk.GetLength() == 0) && (m_crs == ClusterResourceOffline))) { DDV_RequiredText(pDX, IDC_PP_DISKS_PARAMS_DISK, IDC_PP_DISKS_PARAMS_DISK_LABEL, m_strDisk); m_dwSignature = (DWORD)m_cboxDisk.GetItemData(m_cboxDisk.GetCurSel()); ASSERT(m_dwSignature != 0); } // if: not offline with an empty disk string
} // if: Back button not pressed
} // if: saving data
} // if: not saving or haven't saved yet
CBasePropertyPage::DoDataExchange(pDX);
} //*** CPhysDiskParamsPage::DoDataExchange()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::OnInitDialog
//
// Routine Description:
// Handler for the WM_INITDIALOG message.
//
// Arguments:
// None.
//
// Return Value:
// TRUE We need the focus to be set for us.
// FALSE We already set the focus to the proper control.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CPhysDiskParamsPage::OnInitDialog(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
CBasePropertyPage::OnInitDialog();
// Set the combobox as read-only if not creating a new resource.
m_cboxDisk.EnableWindow(BWizard());
// Fill the disks list.
FillList();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
} //*** CPhysDiskParamsPage::OnInitDialog()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::OnSetActive
//
// Routine Description:
// Handler for the PSN_SETACTIVE message.
//
// Arguments:
// None.
//
// Return Value:
// TRUE Page successfully initialized.
// FALSE Page not initialized.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CPhysDiskParamsPage::OnSetActive(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Enable/disable the Next/Finish button.
if (BWizard()) { if (m_strDisk.GetLength() == 0) EnableNext(FALSE); else EnableNext(TRUE); } // if: enable/disable the Next button
return CBasePropertyPage::OnSetActive();
} //*** CPhysDiskParamsPage::OnSetActive()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::BApplyChanges
//
// Routine Description:
// Apply changes made on the page.
//
// Arguments:
// None.
//
// Return Value:
// TRUE Page successfully applied.
// FALSE Error applying page.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CPhysDiskParamsPage::BApplyChanges(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
CWaitCursor wc;
if (!( (m_strDisk.GetLength() == 0) && (m_crs == ClusterResourceOffline))) { // Call the base class method.
if (!CBasePropertyPage::BApplyChanges()) return FALSE;
// Reread the disk info and the available disks.
// Ignore errors because we can't do anything about it at this point anyway.
BGetAvailableDisks(); BGetDiskInfo();
// Refill the combobox.
FillList(); } // if: not offline with an empty disk string
return TRUE;
} //*** CPhysDiskParamsPage::BApplyChanges()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::OnChangeDisk
//
// Routine Description:
// Handler for the CBN_SELCHANGE message on the Disks combobox.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CPhysDiskParamsPage::OnChangeDisk(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
OnChangeCtrl();
if (BWizard()) { if (m_cboxDisk.GetWindowTextLength() == 0) EnableNext(FALSE); else EnableNext(TRUE); } // if: in a wizard
} //*** CPhysDiskParamsPage::OnChangeDisk()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::BGetAvailableDisks
//
// Routine Description:
// Get the list of disks for this type of resource that can be assigned
// to a resource.
//
// Arguments:
// None.
//
// Return Value:
// TRUE The operation was successful.
// FALSE The operation failed.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CPhysDiskParamsPage::BGetAvailableDisks(void) { DWORD dwStatus = ERROR_SUCCESS; DWORD cbDiskInfo = sizeof(CLUSPROP_DWORD) + sizeof(CLUSPROP_SCSI_ADDRESS) + sizeof(CLUSPROP_DISK_NUMBER) + sizeof(CLUSPROP_PARTITION_INFO) + sizeof(CLUSPROP_SYNTAX); PBYTE pbDiskInfo = NULL;
try { // Get disk info.
pbDiskInfo = new BYTE[cbDiskInfo]; dwStatus = ClusterResourceTypeControl( Peo()->Hcluster(), Peo()->PrdResData()->m_strResTypeName, NULL, CLUSCTL_RESOURCE_TYPE_STORAGE_GET_AVAILABLE_DISKS, NULL, 0, pbDiskInfo, cbDiskInfo, &cbDiskInfo ); if (dwStatus == ERROR_MORE_DATA) { delete [] pbDiskInfo; pbDiskInfo = new BYTE[cbDiskInfo]; dwStatus = ClusterResourceTypeControl( Peo()->Hcluster(), Peo()->PrdResData()->m_strResTypeName, NULL, CLUSCTL_RESOURCE_TYPE_STORAGE_GET_AVAILABLE_DISKS, NULL, 0, pbDiskInfo, cbDiskInfo, &cbDiskInfo ); } // if: buffer too small
} // try
catch (CMemoryException * pme) { pme->Delete(); dwStatus = ERROR_NOT_ENOUGH_MEMORY; } // catch: CMemoryException
if (dwStatus != ERROR_SUCCESS) { CNTException nte( dwStatus, IDS_GET_AVAILABLE_DISKS_ERROR, Peo()->PrdResData()->m_strResTypeName, NULL, FALSE /*bAutoDelete*/ ); delete [] pbDiskInfo; nte.ReportError(); nte.Delete(); return FALSE; } // if: error getting disk info
delete [] m_pbAvailDiskInfo; m_pbAvailDiskInfo = pbDiskInfo; m_cbAvailDiskInfo = cbDiskInfo;
return TRUE;
} //*** CPhysDiskParamsPage::BGetAvailableDisks()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::BGetDiskInfo
//
// Routine Description:
// Get information about the currently selected disk.
//
// Arguments:
// None.
//
// Return Value:
// TRUE The operation was successful.
// FALSE The operation failed.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CPhysDiskParamsPage::BGetDiskInfo(void) { DWORD dwStatus = ERROR_SUCCESS; DWORD cbDiskInfo = sizeof(CLUSPROP_DWORD) + sizeof(CLUSPROP_SCSI_ADDRESS) + sizeof(CLUSPROP_DISK_NUMBER) + sizeof(CLUSPROP_PARTITION_INFO) + sizeof(CLUSPROP_SYNTAX); PBYTE pbDiskInfo = NULL;
try { // Get disk info.
pbDiskInfo = new BYTE[cbDiskInfo]; dwStatus = ClusterResourceControl( Peo()->PrdResData()->m_hresource, NULL, CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO, NULL, 0, pbDiskInfo, cbDiskInfo, &cbDiskInfo ); if (dwStatus == ERROR_MORE_DATA) { delete [] pbDiskInfo; pbDiskInfo = new BYTE[cbDiskInfo]; dwStatus = ClusterResourceControl( Peo()->PrdResData()->m_hresource, NULL, CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO, NULL, 0, pbDiskInfo, cbDiskInfo, &cbDiskInfo ); } // if: buffer too small
} // try
catch (CMemoryException * pme) { pme->Delete(); dwStatus = ERROR_NOT_ENOUGH_MEMORY; } // catch: CMemoryException
if (dwStatus != ERROR_SUCCESS) { CNTException nte( dwStatus, IDS_GET_DISK_INFO_ERROR, Peo()->PrdResData()->m_strName, NULL, FALSE /*bAutoDelete*/ ); delete [] pbDiskInfo; nte.ReportError(); nte.Delete(); return FALSE; } // if: error getting disk info
delete [] m_pbDiskInfo; m_pbDiskInfo = pbDiskInfo; m_cbDiskInfo = cbDiskInfo;
return TRUE;
} //*** CPhysDiskParamsPage::BGetDiskInfo()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::BStringFromDiskInfo
//
// Routine Description:
// Convert disk information to a string for display.
//
// Arguments:
// rbuf [IN OUT] Buffer pointer.
// cbBuf [IN] Number of bytes in the buffer.
// rstr [OUT] String to fill.
// pdwSignature [OUT] Signature associated with the disk info being
// returned.
//
// Return Value:
// TRUE A string was produced from disk info.
// FALSE No string could be produced.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CPhysDiskParamsPage::BStringFromDiskInfo( IN OUT CLUSPROP_BUFFER_HELPER & rbuf, IN DWORD cbBuf, OUT CString & rstr, OUT DWORD * pdwSignature // = NULL
) const { CString strPartitionInfo; DWORD dwSignature = 0; DWORD cbData; BOOL bDisplay;
ASSERT(cbBuf > 0); ASSERT(rbuf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK);
rstr = _T("");
if (rbuf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) { do { // Calculate the size of the value.
cbData = sizeof(*rbuf.pValue) + ALIGN_CLUSPROP(rbuf.pValue->cbLength); ASSERT(cbData <= cbBuf);
// Parse the value.
if (rbuf.pSyntax->dw == CLUSPROP_SYNTAX_DISK_SIGNATURE) { // Save the signature.
dwSignature = rbuf.pDwordValue->dw; ASSERT(dwSignature != 0); } // if: signature
else if (rbuf.pSyntax->dw == CLUSPROP_SYNTAX_PARTITION_INFO) { // Add the partition to the string if it is a usable partition
// and hasn't been added already. If the resource is offline,
// don't check the usable flag.
bDisplay = ( rstr.Find(rbuf.pPartitionInfoValue->szDeviceName) == -1 ); if ( bDisplay && ( m_crs == ClusterResourceOnline ) ) { bDisplay = (rbuf.pPartitionInfoValue->dwFlags & CLUSPROP_PIFLAG_USABLE) == CLUSPROP_PIFLAG_USABLE; } // if: resource is online
if (bDisplay) { try { strPartitionInfo.Format( (rbuf.pPartitionInfoValue->szVolumeLabel[0] ? _T("%ls (%ls) ") : _T("%ls ")), rbuf.pPartitionInfoValue->szDeviceName, rbuf.pPartitionInfoValue->szVolumeLabel ); rstr += strPartitionInfo; if (pdwSignature != NULL) { _ASSERTE(dwSignature != 0); *pdwSignature = dwSignature; } // if: caller wants signature as well
} // try
catch (...) { // Ignore all errors because there is really nothing we can do.
// Displaying a message isn't really very useful.
} // catch: Anything
} // if: partition should be displayed
} // else if: partition info
// Advance the buffer pointer
rbuf.pb += cbData; cbBuf -= cbData;
} while ( (rbuf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) && (rbuf.pSyntax->dw != CLUSPROP_SYNTAX_DISK_SIGNATURE)); } // if: not an endmark
return (rstr.GetLength() > 0);
} //*** CPhysDiskParamsPage::BStringFromDiskInfo()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CPhysDiskParamsPage::FillList
//
// Routine Description:
// Fill the list of disks.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CPhysDiskParamsPage::FillList(void) { CString strDisk; DWORD dwSignature; int icbox;
// Clear the list first.
m_cboxDisk.ResetContent();
// Add the disk info first.
if (m_cbDiskInfo > 0) { CLUSPROP_BUFFER_HELPER buf; buf.pb = m_pbDiskInfo; if (BStringFromDiskInfo(buf, m_cbDiskInfo, m_strDisk, &dwSignature)) { ASSERT(dwSignature != 0); icbox = m_cboxDisk.AddString(m_strDisk); m_cboxDisk.SetItemData(icbox, dwSignature); } // if: disk info was found
} // if: there is disk info
// Now add the available disk info.
if (m_cbAvailDiskInfo > 0) { CString strDisk; CLUSPROP_BUFFER_HELPER buf; buf.pb = m_pbAvailDiskInfo; while (buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) { if (BStringFromDiskInfo(buf, m_cbAvailDiskInfo, strDisk, &dwSignature)) { ASSERT(dwSignature != 0); icbox = m_cboxDisk.AddString(strDisk); m_cboxDisk.SetItemData(icbox, dwSignature); } // if: disk info was found
} // while: more entries in the list
} // if: there is available disk info
// Now select an item in the list.
if (m_strDisk.GetLength() > 0) { int nIndex;
nIndex = m_cboxDisk.FindStringExact(-1, m_strDisk); m_cboxDisk.SetCurSel(nIndex); } // if: there is a selected item
} //*** CPhysDiskParamsPage::FillList()
|