813 lines
18 KiB
C++
813 lines
18 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1998 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
FTMan
|
||
|
|
||
|
File Name:
|
||
|
|
||
|
FTUtil.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implementation of FT utilities
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Cristian Teodorescu October 29, 1998
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
#include "DiskMap.h"
|
||
|
#include "FTUtil.h"
|
||
|
#include "Global.h"
|
||
|
#include "Item.h"
|
||
|
#include "Resource.h"
|
||
|
|
||
|
extern "C"
|
||
|
{
|
||
|
#include <FTAPI.h>
|
||
|
}
|
||
|
|
||
|
#include <ntddft2.h>
|
||
|
#include <winioctl.h>
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
Global function: FTBreak
|
||
|
|
||
|
Purpose: Break a logical volume
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID llVolID
|
||
|
ID of the logical volume
|
||
|
|
||
|
Return value: TRUE if the volume is broken successfully
|
||
|
*/
|
||
|
|
||
|
BOOL FTBreak( FT_LOGICAL_DISK_ID llVolID )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
BOOL bResult;
|
||
|
|
||
|
DisplayStatusBarMessage( IDS_STATUS_FTBREAK );
|
||
|
|
||
|
bResult = FtBreakLogicalDisk( llVolID );
|
||
|
|
||
|
if( bResult )
|
||
|
{
|
||
|
//AfxMessageBox( IDS_MSG_FTBREAK, MB_ICONINFORMATION );
|
||
|
}
|
||
|
else
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTBREAK );
|
||
|
|
||
|
DisplayStatusBarMessage( AFX_IDS_IDLEMESSAGE );
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTChkIO
|
||
|
|
||
|
Purpose: Check the IO status of a logical volume
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID llVolID
|
||
|
ID of the logical volume
|
||
|
[OUT] BOOL* pbOK
|
||
|
The result of the IO check
|
||
|
|
||
|
Return value: TRUE if the IO check operation succeeded
|
||
|
*/
|
||
|
|
||
|
BOOL FTChkIO( FT_LOGICAL_DISK_ID llVolID, BOOL* pbOK )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
BOOL bResult;
|
||
|
|
||
|
bResult = FtCheckIo( llVolID, pbOK );
|
||
|
|
||
|
/*
|
||
|
if( bResult )
|
||
|
{
|
||
|
CString strMsg, strOK;
|
||
|
strOK.LoadString( bOK ? IDS_OK : IDS_NOTOK );
|
||
|
AfxFormatString1(strMsg, IDS_MSG_FTCHKIO, strOK);
|
||
|
AfxMessageBox(strMsg,MB_ICONINFORMATION);
|
||
|
}
|
||
|
else
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTCHKIO );
|
||
|
*/
|
||
|
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTExtend
|
||
|
|
||
|
Purpose: Extend the file system of a volume to the maximum possible
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID llVolID
|
||
|
ID of the logical volume
|
||
|
|
||
|
Return value: TRUE if the file system is extended successfully
|
||
|
*/
|
||
|
|
||
|
BOOL FTExtend( FT_LOGICAL_DISK_ID llVolID )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
BOOL bReturn;
|
||
|
HANDLE h;
|
||
|
PARTITION_INFORMATION partInfo;
|
||
|
DISK_GEOMETRY geometry;
|
||
|
ULONG ulBytes;
|
||
|
LONGLONG llNewSectors;
|
||
|
|
||
|
CString strVolumeName;
|
||
|
if( !FTQueryVolumeName( llVolID, strVolumeName ) )
|
||
|
return FALSE;
|
||
|
|
||
|
h = CreateFile( strVolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE );
|
||
|
if( h == INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTEXTEND );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
bReturn = DeviceIoControl( h, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0,
|
||
|
&partInfo, sizeof(partInfo), &ulBytes, NULL );
|
||
|
if( !bReturn )
|
||
|
{
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTEXTEND );
|
||
|
CloseHandle(h);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
bReturn = DeviceIoControl( h, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
|
||
|
&geometry, sizeof(geometry), &ulBytes, NULL );
|
||
|
if( !bReturn )
|
||
|
{
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTEXTEND );
|
||
|
CloseHandle(h);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
llNewSectors = partInfo.PartitionLength.QuadPart / geometry.BytesPerSector;
|
||
|
|
||
|
bReturn = DeviceIoControl( h, FSCTL_EXTEND_VOLUME, &llNewSectors, sizeof(llNewSectors),
|
||
|
NULL, 0, &ulBytes, NULL );
|
||
|
|
||
|
CloseHandle(h);
|
||
|
return bReturn;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTInit
|
||
|
|
||
|
Purpose: Initialize a logical volume with repairing ( or not ) the orphan member
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID llVolID
|
||
|
The ID of the logical volume
|
||
|
[BOOL] bInitOrphans
|
||
|
Initialize the orphan member or not
|
||
|
|
||
|
Return value: TRUE if the logical volume was initialized successfully
|
||
|
*/
|
||
|
BOOL FTInit( FT_LOGICAL_DISK_ID llVolID, BOOL bInitOrphans /* = TRUE */ )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
BOOL bResult;
|
||
|
|
||
|
DisplayStatusBarMessage( IDS_STATUS_FTINIT );
|
||
|
|
||
|
bResult = FtInitializeLogicalDisk( llVolID, bInitOrphans );
|
||
|
|
||
|
if( bResult )
|
||
|
{
|
||
|
//AfxMessageBox( IDS_MSG_FTINIT, MB_ICONINFORMATION );
|
||
|
}
|
||
|
else
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTINIT );
|
||
|
|
||
|
DisplayStatusBarMessage( AFX_IDS_IDLEMESSAGE );
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTMirror
|
||
|
|
||
|
Purpose: Create a mirror set based on the given logical volumes
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID* arrVolID
|
||
|
ID's of the members
|
||
|
[IN] WORD wNumVols
|
||
|
The number of members ( must be 2 )
|
||
|
[OUT] FT_LOGICAL_DISK_ID* pllVolID
|
||
|
Address where the logical volume ID of the new mirror set is to be stored
|
||
|
If NULL then don't return the ID
|
||
|
|
||
|
Return value: TRUE if the mirror set is created successfully
|
||
|
*/
|
||
|
|
||
|
BOOL FTMirror( FT_LOGICAL_DISK_ID* arrVolID, WORD wNumVols, FT_LOGICAL_DISK_ID* pllVolID /* = NULL */ )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
ASSERT( arrVolID );
|
||
|
ASSERT( wNumVols == 2 );
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
BOOL bResult;
|
||
|
FT_MIRROR_SET_CONFIGURATION_INFORMATION configInfo;
|
||
|
FT_LOGICAL_DISK_ID llNewVolID;
|
||
|
LONGLONG llMemberSize, llZeroMemberSize;
|
||
|
|
||
|
DisplayStatusBarMessage( IDS_STATUS_FTMIRROR );
|
||
|
|
||
|
configInfo.MemberSize = MAXLONGLONG;
|
||
|
|
||
|
for( int i = 0; i < wNumVols; i++ )
|
||
|
{
|
||
|
bResult = FtQueryLogicalDiskInformation( arrVolID[i], NULL, &llMemberSize, 0,
|
||
|
NULL, NULL, 0, NULL, 0, NULL );
|
||
|
if( !bResult )
|
||
|
{
|
||
|
DisplaySystemErrorMessage(IDS_ERR_RETRIEVING_VOL_INFO);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if( llMemberSize < configInfo.MemberSize )
|
||
|
configInfo.MemberSize = llMemberSize;
|
||
|
|
||
|
if( i == 0 )
|
||
|
llZeroMemberSize = llMemberSize;
|
||
|
}
|
||
|
|
||
|
if( llMemberSize < llZeroMemberSize )
|
||
|
{
|
||
|
CString str, strSize1, strSize2;
|
||
|
FormatVolumeSize( strSize1, llZeroMemberSize );
|
||
|
FormatVolumeSize( strSize2, llMemberSize );
|
||
|
AfxFormatString2(str, IDS_QST_FTMIRROR, strSize1, strSize2);
|
||
|
if( IDYES != AfxMessageBox( str, MB_YESNO | MB_DEFBUTTON2 ) )
|
||
|
{
|
||
|
DisplayStatusBarMessage( AFX_IDS_IDLEMESSAGE );
|
||
|
return FALSE;
|
||
|
}
|
||
|
wc.Restore();
|
||
|
}
|
||
|
|
||
|
bResult = FtCreateLogicalDisk( FtMirrorSet, wNumVols, arrVolID, sizeof(configInfo),
|
||
|
&configInfo, &llNewVolID );
|
||
|
|
||
|
if( bResult )
|
||
|
{
|
||
|
//AfxMessageBox( IDS_MSG_FTMIRROR, MB_ICONINFORMATION );
|
||
|
if( pllVolID )
|
||
|
*pllVolID = llNewVolID;
|
||
|
}
|
||
|
else
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTMIRROR );
|
||
|
|
||
|
DisplayStatusBarMessage( AFX_IDS_IDLEMESSAGE );
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTOrphan
|
||
|
|
||
|
Purpose: Orphan the given member of the given logical volume.
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID llVolID
|
||
|
ID of the logical volume
|
||
|
[IN] WORD wMember
|
||
|
Zero-based index of the member to be orphaned
|
||
|
|
||
|
Return value: TRUE if the member is orphaned successfully
|
||
|
*/
|
||
|
|
||
|
BOOL FTOrphan( FT_LOGICAL_DISK_ID llVolID, WORD wMember )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
BOOL bResult;
|
||
|
|
||
|
DisplayStatusBarMessage( IDS_STATUS_FTORPHAN );
|
||
|
|
||
|
bResult = FtOrphanLogicalDiskMember( llVolID, wMember );
|
||
|
|
||
|
if( bResult )
|
||
|
{
|
||
|
// AfxMessageBox( IDS_MSG_FTORPHAN, MB_ICONINFORMATION );
|
||
|
}
|
||
|
else
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTORPHAN );
|
||
|
|
||
|
DisplayStatusBarMessage( AFX_IDS_IDLEMESSAGE );
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTPart
|
||
|
|
||
|
Purpose: Converts a physical partition into a FT partition
|
||
|
|
||
|
Parameters: [IN] CString& strVolumeName
|
||
|
Volume name of the physical partition
|
||
|
It should be like this: "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
|
||
|
[IN] TCHAR cDriveLetter
|
||
|
The drive letter of the physical partition
|
||
|
'\0' if none
|
||
|
[OUT] FT_LOGICAL_DISK_ID* pllVolID
|
||
|
Address where the logical volume ID of the new FT partitions to be stored
|
||
|
If NULL then don't return the ID
|
||
|
|
||
|
Return value: TRUE if the FT partition is created successfully
|
||
|
*/
|
||
|
|
||
|
BOOL FTPart( const CString& strVolumeName, TCHAR cDriveLetter /* =_T('\0') */, FT_LOGICAL_DISK_ID* pllVolID /* = NULL */ )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
BOOL bResult;
|
||
|
HANDLE hPart;
|
||
|
FT_LOGICAL_DISK_ID llVolID;
|
||
|
|
||
|
// First open the partition
|
||
|
hPart = OpenVolume( strVolumeName );
|
||
|
|
||
|
if( hPart == INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTPART );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Second create the logical volume
|
||
|
bResult = FtCreatePartitionLogicalDisk( hPart, &llVolID );
|
||
|
CloseHandle(hPart);
|
||
|
|
||
|
if( bResult )
|
||
|
{
|
||
|
//AfxMessageBox( IDS_MSG_FTPART, MB_ICONINFORMATION );
|
||
|
if( cDriveLetter != _T('\0') )
|
||
|
{
|
||
|
#ifdef UNICODE
|
||
|
cDriveLetter = (WCHAR)(towupper( cDriveLetter ));
|
||
|
#else
|
||
|
cDriveLetter = (char)(toupper( cDriveLetter ));
|
||
|
#endif
|
||
|
|
||
|
FtSetStickyDriveLetter( llVolID, (UCHAR) cDriveLetter );
|
||
|
}
|
||
|
if( pllVolID )
|
||
|
*pllVolID = llVolID;
|
||
|
}
|
||
|
else
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTPART );
|
||
|
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTRegen
|
||
|
|
||
|
Purpose: Replace a member of a logical volume with another logical volume and start the
|
||
|
regeneration process.
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID llVolID
|
||
|
ID of the logical volume whose member is to be replaced
|
||
|
[IN] WORD wMember
|
||
|
Zero-based index of the member to be replced
|
||
|
[IN] FT_LOGICAL_DISK_ID llReplVolID
|
||
|
ID of the replacement
|
||
|
[OUT] FT_LOGICAL_DISK_ID* pllVolID
|
||
|
Address where the logical volume ID of the new set is to be stored
|
||
|
If NULL then don't return the ID
|
||
|
|
||
|
Return value: TRUE if the stripe set is created successfully
|
||
|
*/
|
||
|
|
||
|
BOOL FTRegen( FT_LOGICAL_DISK_ID llVolID, WORD wMember, FT_LOGICAL_DISK_ID llReplVolID,
|
||
|
FT_LOGICAL_DISK_ID* pllVolID /* =NULL */ )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
BOOL bResult;
|
||
|
FT_LOGICAL_DISK_ID llNewVolID;
|
||
|
|
||
|
DisplayStatusBarMessage( IDS_STATUS_FTREGEN );
|
||
|
|
||
|
bResult = FtReplaceLogicalDiskMember( llVolID, wMember, llReplVolID, &llNewVolID );
|
||
|
|
||
|
if( bResult )
|
||
|
{
|
||
|
//AfxMessageBox( IDS_MSG_FTREGEN, MB_ICONINFORMATION );
|
||
|
if( pllVolID )
|
||
|
*pllVolID = llNewVolID;
|
||
|
}
|
||
|
else
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTREGEN );
|
||
|
|
||
|
DisplayStatusBarMessage( AFX_IDS_IDLEMESSAGE );
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTStripe
|
||
|
|
||
|
Purpose: Create a stripe set based on the given logical volumes
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID* arrVolID
|
||
|
ID's of the members
|
||
|
[IN] WORD wNumVols
|
||
|
The number of members
|
||
|
[IN] LONGLONG llStripeSize
|
||
|
The size of the stripe chunks
|
||
|
[OUT] FT_LOGICAL_DISK_ID* pllVolID
|
||
|
Address where the logical volume ID of the new stripe set is to be stored
|
||
|
If NULL then don't return the ID
|
||
|
|
||
|
Return value: TRUE if the stripe set is created successfully
|
||
|
*/
|
||
|
|
||
|
BOOL FTStripe( FT_LOGICAL_DISK_ID* arrVolID, WORD wNumVols, ULONG ulStripeSize, FT_LOGICAL_DISK_ID* pllVolID /* = NULL */)
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
ASSERT( arrVolID );
|
||
|
ASSERT( wNumVols >= 2 );
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
BOOL bResult;
|
||
|
FT_STRIPE_SET_CONFIGURATION_INFORMATION configInfo;
|
||
|
FT_LOGICAL_DISK_ID llNewVolID;
|
||
|
|
||
|
DisplayStatusBarMessage( IDS_STATUS_FTSTRIPE );
|
||
|
|
||
|
configInfo.StripeSize = ulStripeSize;
|
||
|
bResult = FtCreateLogicalDisk( FtStripeSet, wNumVols, arrVolID, sizeof(configInfo),
|
||
|
&configInfo, &llNewVolID );
|
||
|
|
||
|
if( bResult )
|
||
|
{
|
||
|
//AfxMessageBox( IDS_MSG_FTSTRIPE, MB_ICONINFORMATION );
|
||
|
if( pllVolID )
|
||
|
*pllVolID = llNewVolID;
|
||
|
}
|
||
|
else
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTSTRIPE );
|
||
|
|
||
|
DisplayStatusBarMessage( AFX_IDS_IDLEMESSAGE );
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTSWP
|
||
|
|
||
|
Purpose: Create a stripe set with parity based on the given logical volumes
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID* arrVolID
|
||
|
ID's of the members
|
||
|
[IN] WORD wNumVols
|
||
|
The number of members
|
||
|
[IN] LONGLONG llStripeSize
|
||
|
The size of the stripe chunks
|
||
|
[OUT] FT_LOGICAL_DISK_ID* pllVolID
|
||
|
Address where the logical volume ID of the new stripe set with parity is to be stored
|
||
|
If NULL then don't return the ID
|
||
|
|
||
|
Return value: TRUE if the stripe set with parity is created successfully
|
||
|
*/
|
||
|
|
||
|
BOOL FTSWP( FT_LOGICAL_DISK_ID* arrVolID, WORD wNumVols, ULONG ulStripeSize, FT_LOGICAL_DISK_ID* pllVolID /* = NULL */ )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
ASSERT( arrVolID );
|
||
|
ASSERT( wNumVols >= 3 );
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
BOOL bResult;
|
||
|
FT_STRIPE_SET_WITH_PARITY_CONFIGURATION_INFORMATION configInfo;
|
||
|
FT_LOGICAL_DISK_ID llNewVolID;
|
||
|
LONGLONG llMemberSize;
|
||
|
|
||
|
DisplayStatusBarMessage( IDS_STATUS_FTSWP );
|
||
|
|
||
|
configInfo.MemberSize = MAXLONGLONG;
|
||
|
for( int i=0; i < wNumVols; i++ )
|
||
|
{
|
||
|
bResult = FtQueryLogicalDiskInformation( arrVolID[i], NULL, &llMemberSize, 0,
|
||
|
NULL, NULL, 0, NULL, 0, NULL );
|
||
|
|
||
|
if( !bResult )
|
||
|
{
|
||
|
DisplaySystemErrorMessage(IDS_ERR_RETRIEVING_VOL_INFO);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if( llMemberSize < configInfo.MemberSize )
|
||
|
configInfo.MemberSize = llMemberSize;
|
||
|
}
|
||
|
|
||
|
configInfo.StripeSize = ulStripeSize;
|
||
|
|
||
|
bResult = FtCreateLogicalDisk( FtStripeSetWithParity, wNumVols, arrVolID, sizeof( configInfo),
|
||
|
&configInfo, &llNewVolID );
|
||
|
|
||
|
if( bResult )
|
||
|
{
|
||
|
//AfxMessageBox(IDS_MSG_FTSWP, MB_ICONINFORMATION);
|
||
|
if( pllVolID )
|
||
|
*pllVolID = llNewVolID;
|
||
|
}
|
||
|
else
|
||
|
DisplaySystemErrorMessage(IDS_ERR_FTSWP);
|
||
|
|
||
|
DisplayStatusBarMessage( AFX_IDS_IDLEMESSAGE );
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTVolSet
|
||
|
|
||
|
Purpose: Create a volume set based on the given logical volumes
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID* arrVolID
|
||
|
ID's of the members
|
||
|
[IN] WORD wNumVols
|
||
|
The number of members
|
||
|
[OUT] FT_LOGICAL_DISK_ID* pllVolID
|
||
|
Address where the logical volume ID of the new volume set is to be stored
|
||
|
If NULL then don't return the ID
|
||
|
|
||
|
Return value: TRUE if the volume set is created successfully
|
||
|
*/
|
||
|
|
||
|
BOOL FTVolSet( FT_LOGICAL_DISK_ID* arrVolID, WORD wNumVols, FT_LOGICAL_DISK_ID* pllVolID /* = NULL */)
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
ASSERT( arrVolID );
|
||
|
ASSERT( wNumVols >= 2 );
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
BOOL bResult;
|
||
|
FT_LOGICAL_DISK_ID llNewVolID;
|
||
|
|
||
|
DisplayStatusBarMessage( IDS_STATUS_FTVOLSET );
|
||
|
|
||
|
bResult = FtCreateLogicalDisk( FtVolumeSet, wNumVols, arrVolID, 0,
|
||
|
NULL, &llNewVolID );
|
||
|
|
||
|
if( bResult )
|
||
|
{
|
||
|
//AfxMessageBox( IDS_MSG_FTVOLSET, MB_ICONINFORMATION );
|
||
|
if( pllVolID )
|
||
|
*pllVolID = llNewVolID;
|
||
|
}
|
||
|
else
|
||
|
DisplaySystemErrorMessage( IDS_ERR_FTVOLSET );
|
||
|
|
||
|
DisplayStatusBarMessage( AFX_IDS_IDLEMESSAGE );
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
BOOL FTQueryNTDeviceName( FT_LOGICAL_DISK_ID llVolID, CString& strNTName )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
HANDLE h;
|
||
|
FT_QUERY_NT_DEVICE_NAME_FOR_LOGICAL_DISK_INPUT Input;
|
||
|
ULONG ulOutputSize;
|
||
|
PFT_QUERY_NT_DEVICE_NAME_FOR_LOGICAL_DISK_OUTPUT pOutput;
|
||
|
BOOL b;
|
||
|
ULONG ulBytes;
|
||
|
|
||
|
h = CreateFile(_T("\\\\.\\FtControl"), GENERIC_READ,
|
||
|
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
|
||
|
INVALID_HANDLE_VALUE);
|
||
|
if (h == INVALID_HANDLE_VALUE)
|
||
|
return FALSE;
|
||
|
|
||
|
Input.RootLogicalDiskId = llVolID;
|
||
|
ulOutputSize = MAX_PATH;
|
||
|
pOutput = (PFT_QUERY_NT_DEVICE_NAME_FOR_LOGICAL_DISK_OUTPUT)LocalAlloc(0, ulOutputSize);
|
||
|
if (!pOutput)
|
||
|
{
|
||
|
CloseHandle(h);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
b = DeviceIoControl(h, FT_QUERY_NT_DEVICE_NAME_FOR_LOGICAL_DISK, &Input,
|
||
|
sizeof(Input), pOutput, ulOutputSize, &ulBytes, NULL);
|
||
|
CloseHandle(h);
|
||
|
|
||
|
if (!b )
|
||
|
{
|
||
|
LocalFree(pOutput);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
CopyW2Str( strNTName, pOutput->NtDeviceName, pOutput->NumberOfCharactersInNtDeviceName );
|
||
|
|
||
|
LocalFree(pOutput);
|
||
|
return TRUE;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTGetDisksSet
|
||
|
|
||
|
Purpose: Retrieves all disks the logical volume is located on
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID llVolID
|
||
|
The ID of the logical volume
|
||
|
[OUT] CULONGSet& setDisks
|
||
|
The set of disks
|
||
|
|
||
|
Return value: TRUE if the functions succeeds
|
||
|
*/
|
||
|
|
||
|
BOOL FTGetDisksSet( FT_LOGICAL_DISK_ID llVolID, CULONGSet& setDisks )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
FT_LOGICAL_DISK_TYPE nVolType;
|
||
|
LONGLONG llVolSize;
|
||
|
WORD numMembers;
|
||
|
FT_LOGICAL_DISK_ID members[100];
|
||
|
CHAR stateInfo[100];
|
||
|
CHAR configInfo[100];
|
||
|
|
||
|
setDisks.RemoveAll();
|
||
|
|
||
|
// Read all information related to this logical volume
|
||
|
BOOL b = FtQueryLogicalDiskInformation ( llVolID,
|
||
|
&nVolType,
|
||
|
&llVolSize,
|
||
|
100,
|
||
|
members,
|
||
|
&numMembers,
|
||
|
sizeof(configInfo),
|
||
|
&configInfo,
|
||
|
sizeof(stateInfo),
|
||
|
&stateInfo );
|
||
|
if(!b)
|
||
|
return FALSE;
|
||
|
|
||
|
if( nVolType == FtPartition )
|
||
|
{
|
||
|
setDisks.Add( ((PFT_PARTITION_CONFIGURATION_INFORMATION)configInfo)->DiskNumber );
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// The disks set is the reunion of all members disk sets
|
||
|
for( WORD i = 0; i < numMembers; i++ )
|
||
|
{
|
||
|
CULONGSet setMemberDisks;
|
||
|
if( !FTGetDisksSet( members[i], setMemberDisks ) )
|
||
|
return FALSE;
|
||
|
setDisks += setMemberDisks;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTQueryVolumeName
|
||
|
|
||
|
Purpose: Retrieve the volume name of a logical volume
|
||
|
The volume name should be like this: "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
|
||
|
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID llVolID
|
||
|
The ID of the logical volume
|
||
|
[OUT] CString& strVolumeName
|
||
|
Reference to a string to receive the volume name
|
||
|
|
||
|
Return value: TRUE if the functions succeeds
|
||
|
*/
|
||
|
|
||
|
BOOL FTQueryVolumeName( FT_LOGICAL_DISK_ID llVolID, CString& strVolumeName )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
CString strNTName;
|
||
|
|
||
|
if (!FTQueryNTDeviceName( llVolID, strNTName ) )
|
||
|
return FALSE;
|
||
|
|
||
|
TCHAR cDriveLetter;
|
||
|
return QueryDriveLetterAndVolumeName( strNTName, cDriveLetter, strVolumeName );
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: FTDelete
|
||
|
|
||
|
Purpose: Delete a logical volume by deleting all its physical partitions
|
||
|
|
||
|
|
||
|
Parameters: [IN] FT_LOGICAL_DISK_ID llVolID
|
||
|
The ID of the logical volume
|
||
|
|
||
|
Return value: TRUE if all its physical partitions were deleted
|
||
|
*/
|
||
|
|
||
|
BOOL FTDelete( FT_LOGICAL_DISK_ID llVolID )
|
||
|
{
|
||
|
MY_TRY
|
||
|
|
||
|
CWaitCursor wc;
|
||
|
FT_LOGICAL_DISK_TYPE nVolType;
|
||
|
LONGLONG llVolSize;
|
||
|
WORD numMembers;
|
||
|
FT_LOGICAL_DISK_ID members[100];
|
||
|
CHAR stateInfo[100];
|
||
|
CHAR configInfo[100];
|
||
|
|
||
|
// Read all information related to this logical volume
|
||
|
BOOL b = FtQueryLogicalDiskInformation ( llVolID,
|
||
|
&nVolType,
|
||
|
&llVolSize,
|
||
|
100,
|
||
|
members,
|
||
|
&numMembers,
|
||
|
sizeof(configInfo),
|
||
|
&configInfo,
|
||
|
sizeof(stateInfo),
|
||
|
&stateInfo );
|
||
|
if(!b)
|
||
|
{
|
||
|
::DisplaySystemErrorMessage( IDS_ERR_RETRIEVING_VOL_INFO );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if( nVolType == FtPartition )
|
||
|
{
|
||
|
CDiskMap diskMap( ((PFT_PARTITION_CONFIGURATION_INFORMATION)configInfo)->DiskNumber );
|
||
|
return diskMap.DeletePartition( ((PFT_PARTITION_CONFIGURATION_INFORMATION)configInfo)->ByteOffset );
|
||
|
}
|
||
|
|
||
|
// Delete all members
|
||
|
BOOL bResult = TRUE;
|
||
|
for( WORD i = 0; i < numMembers; i++ )
|
||
|
bResult = FTDelete( members[i] ) && bResult;
|
||
|
|
||
|
return bResult;
|
||
|
|
||
|
MY_CATCH_AND_THROW
|
||
|
}
|