Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1962 lines
68 KiB

/*++
Copyright (c) 1999-2001 Microsoft Corporation
Abstract:
@doc
@module process.cpp | The processing functions for the VSS admin CLI
@end
Author:
Adi Oltean [aoltean] 04/04/2000
TBD:
Add comments.
Revision History:
Name Date Comments
aoltean 04/04/2000 Created
ssteiner 10/20/2000 Changed List SnapshotSets to use more limited VSS queries.
--*/
/////////////////////////////////////////////////////////////////////////////
// Includes
// The rest of includes are specified here
#include "vssadmin.h"
#include "commandverifier.h"
#include "versionspecific.h"
////////////////////////////////////////////////////////////////////////
// Standard foo for file name aliasing. This code block must be after
// all includes of VSS header files.
//
#ifdef VSS_FILE_ALIAS
#undef VSS_FILE_ALIAS
#endif
#define VSS_FILE_ALIAS "ADMPROCC"
//
////////////////////////////////////////////////////////////////////////
#define VSSADM_INFINITE_DIFFAREA 0xFFFFFFFFFFFFFFFF
#define VSS_CTX_ATTRIB_MASK 0x01F
/////////////////////////////////////////////////////////////////////////////
// Implementation
class CVssAdmSnapshotSetEntry {
public:
// Constructor - Throws NOTHING
CVssAdmSnapshotSetEntry(
IN VSS_ID SnapshotSetId,
IN INT nOriginalSnapshotsCount
) : m_SnapshotSetId( SnapshotSetId ),
m_nOriginalSnapshotCount(nOriginalSnapshotsCount)
{ }
~CVssAdmSnapshotSetEntry()
{
// Have to delete all snapshots entries
int iCount = GetSnapshotCount();
for ( int i = 0; i < iCount; ++i )
{
VSS_SNAPSHOT_PROP *pSSProp;
pSSProp = GetSnapshotAt( i );
::VssFreeSnapshotProperties(pSSProp);
delete pSSProp;
}
}
// Add new snapshot to the snapshot set
HRESULT AddSnapshot(
IN VSS_SNAPSHOT_PROP *pVssSnapshotProp )
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdmSnapshotSetEntry::AddSnapshot" );
HRESULT hr = S_OK;
try
{
VSS_SNAPSHOT_PROP *pNewVssSnapshotProp = new VSS_SNAPSHOT_PROP;
if ( pNewVssSnapshotProp == NULL )
ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
*pNewVssSnapshotProp = *pVssSnapshotProp;
//
// Transfer of pointer ownership
//
if ( !m_mapSnapshots.Add( pNewVssSnapshotProp->m_SnapshotId, pNewVssSnapshotProp ) )
{
delete pNewVssSnapshotProp;
ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
}
}
BS_STANDARD_CATCH();
return hr;
}
INT GetSnapshotCount() { return m_mapSnapshots.GetSize(); }
INT GetOriginalSnapshotCount() { return m_nOriginalSnapshotCount; }
VSS_ID GetSnapshotSetId() { return m_SnapshotSetId; }
VSS_SNAPSHOT_PROP *GetSnapshotAt(
IN int nIndex )
{
BS_ASSERT( !(nIndex < 0 || nIndex >= GetSnapshotCount()) );
return m_mapSnapshots.GetValueAt( nIndex );
}
private:
VSS_ID m_SnapshotSetId;
INT m_nOriginalSnapshotCount;
CVssSimpleMap<VSS_ID, VSS_SNAPSHOT_PROP *> m_mapSnapshots;
};
// This class queries the list of all snapshots and assembles from the query
// the list of snapshotsets and the volumes which are in the snapshotset.
class CVssAdmSnapshotSets
{
public:
// Constructor
CVssAdmSnapshotSets() { };
void Initialize(
IN LONG lSnapshotContext,
IN VSS_ID FilteredSnapshotSetId,
IN VSS_ID FilteredSnapshotId,
IN VSS_ID FilteredProviderId,
IN LPCWSTR pwszFilteredForVolume
)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdmSnapshotSets::CVssAdmSnapshotSets" );
// Create the coordinator object
CComPtr<IVssCoordinator> pICoord;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VSSCoordinator,
L"Coordinator",
CLSCTX_ALL,
IID_IVssCoordinator,
(IUnknown**)&(pICoord));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
// Set the context
ft.hr = pICoord->SetContext( lSnapshotContext );
//
// If access denied, don't stop, it probably is a backup operator making this
// call. Continue. Also continue if E_NOTIMPL. The coordinator will use the backup context.
//
if ( ft.HrFailed() && ft.hr != E_ACCESSDENIED && ft.hr != E_NOTIMPL )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"SetContext failed with hr = 0x%08lx", ft.hr);
// Get list all snapshots
CComPtr<IVssEnumObject> pIEnumSnapshots;
ft.hr = pICoord->Query( GUID_NULL,
VSS_OBJECT_NONE,
VSS_OBJECT_SNAPSHOT,
&pIEnumSnapshots );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Query failed with hr = 0x%08lx", ft.hr);
// For all snapshots do...
VSS_OBJECT_PROP Prop;
for(;;) {
// Get next element
ULONG ulFetched;
ft.hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
// Test if the cycle is finished
if (ft.hr == S_FALSE) {
BS_ASSERT( ulFetched == 0);
break;
}
// Use auto delete class to manage the snapshot properties
CVssAutoSnapshotProperties cSnap( Prop );
// If filtering, skip entry if snapshot set id is not in the specified snapshot set
if ( ( FilteredSnapshotSetId != GUID_NULL ) &&
!( cSnap->m_SnapshotSetId == FilteredSnapshotSetId ) )
{
continue;
}
// If filtering, skip entry if snapshot id is not in the specified snapshot set
if ( ( FilteredSnapshotId != GUID_NULL ) &&
!( cSnap->m_SnapshotId == FilteredSnapshotId ) )
{
continue;
}
// If filtering, skip entry if provider ID is not in the specified snapshot
if ( ( FilteredProviderId != GUID_NULL ) &&
!( cSnap->m_ProviderId == FilteredProviderId ) )
{
continue;
}
// If filtering, skip entry if FOR volume is not in the specified snapshot
if ( ( pwszFilteredForVolume != NULL ) && ( pwszFilteredForVolume[0] != '\0' ) &&
( ::_wcsicmp( pwszFilteredForVolume, cSnap->m_pwszOriginalVolumeName ) != 0 ) )
{
continue;
}
ft.Trace( VSSDBG_VSSADMIN, L"Snapshot: %s", cSnap->m_pwszOriginalVolumeName );
// Look up the snapshot set id in the list of snapshot sets
CVssAdmSnapshotSetEntry *pcSSE;
pcSSE = m_mapSnapshotSets.Lookup( cSnap->m_SnapshotSetId );
if ( pcSSE == NULL )
{
// Haven't seen this snapshot set before, add it to list
pcSSE = new CVssAdmSnapshotSetEntry( cSnap->m_SnapshotSetId,
cSnap->m_lSnapshotsCount );
if ( pcSSE == NULL )
ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
if ( !m_mapSnapshotSets.Add( cSnap->m_SnapshotSetId, pcSSE ) )
{
delete pcSSE;
ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
}
}
// Now add the snapshot to the snapshot set. Transfer of pointer
// ownership of &Snap.
ft.hr = pcSSE->AddSnapshot( cSnap.GetPtr() );
if ( ft.HrFailed() )
{
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"AddSnapshot failed" );
}
cSnap.Transferred();
}
}
~CVssAdmSnapshotSets()
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdmSnapshotSets::~CVssAdmSnapshotSets" );
// Have to delete all
int iCount;
iCount = m_mapSnapshotSets.GetSize();
for ( int i = 0; i < iCount; ++i )
{
delete m_mapSnapshotSets.GetValueAt( i );
}
}
INT GetSnapshotSetCount() { return m_mapSnapshotSets.GetSize(); }
CVssAdmSnapshotSetEntry *GetSnapshotSetAt(
IN int nIndex )
{
BS_ASSERT( !(nIndex < 0 || nIndex >= GetSnapshotSetCount()) );
return m_mapSnapshotSets.GetValueAt( nIndex );
}
private:
CVssSimpleMap<VSS_ID, CVssAdmSnapshotSetEntry *> m_mapSnapshotSets;
};
void CVssAdminCLI::GetDifferentialSoftwareSnapshotMgmtInterface(
IN VSS_ID ProviderId,
IN IVssSnapshotMgmt *pIMgmt,
OUT IUnknown** ppItf
)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"GetDifferentialSoftwareSnapshotMgmtInterface" );
BS_ASSERT( pIMgmt != NULL );
ft.hr = pIMgmt->GetProviderMgmtInterface( ProviderId, IID_IVssDifferentialSoftwareSnapshotMgmt, ppItf );
if ( ft.HrFailed() )
{
if ( ft.hr == E_NOINTERFACE )
{
// The provider doesn't support this interface
OutputErrorMsg( MSG_ERROR_PROVIDER_DOESNT_SUPPORT_DIFFAREAS, GetOptionValueStr( VSSADM_O_PROVIDER ) );
ft.Throw( VSSDBG_VSSADMIN, S_OK, L"Provider doesn't support diff aras");
}
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"GetProviderMgmtInterface failed with hr = 0x%08lx", ft.hr);
}
}
/////////////////////////////////////////////////////////////////////////////
// Implementation
void CVssAdminCLI::PrintUsage(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::PrintUsage" );
//
// Based on parsed command line type, print detailed command usage if
// eAdmCmd is valid, else print general vssadmin usage
//
if ( m_sParsedCommand.eAdmCmd != VSSADM_C_INVALID )
{
OutputMsg( g_asAdmCommands[m_sParsedCommand.eAdmCmd].lMsgDetail,
g_asAdmCommands[m_sParsedCommand.eAdmCmd].pwszMajorOption,
g_asAdmCommands[m_sParsedCommand.eAdmCmd].pwszMinorOption);
if ( g_asAdmCommands[m_sParsedCommand.eAdmCmd].bShowSSTypes )
DumpSnapshotTypes();
return;
}
//
// Print out header
//
OutputMsg( MSG_USAGE );
//
// Figure out the maximum command length to help with formatting
//
INT idx;
INT iMaxLen = 0;
for ( idx = VSSADM_C_FIRST; idx < VSSADM_C_NUM_COMMANDS; ++idx )
{
if ( dCurrentSKU & g_asAdmCommands[idx].dwSKUs )
{
size_t cCmd;
cCmd = ::wcslen( g_asAdmCommands[idx].pwszMajorOption ) +
::wcslen( g_asAdmCommands[idx].pwszMinorOption ) + 2;
if ( iMaxLen < (INT)cCmd )
iMaxLen = (INT)cCmd;
}
}
//
// Get a string to hold the string
//
CVssAutoPWSZ awszCommand;
awszCommand.Allocate( iMaxLen );
LPWSTR pwszCommand = awszCommand; // will be automatically deleted
//
// Go through the list of commands and print the general information
// about each.
//
for ( idx = VSSADM_C_FIRST; idx < VSSADM_C_NUM_COMMANDS; ++idx )
{
if ( dCurrentSKU & g_asAdmCommands[idx].dwSKUs )
{
// stick both parts of the command together
::wcscpy( pwszCommand, g_asAdmCommands[idx].pwszMajorOption );
::wcscat( pwszCommand, L" " );
::wcscat( pwszCommand, g_asAdmCommands[idx].pwszMinorOption );
// pad with spaces at the end
for ( INT i = (INT) ::wcslen( pwszCommand); i < iMaxLen; ++i )
pwszCommand[i] = L' ';
pwszCommand[iMaxLen] = L'\0';
OutputMsg( g_asAdmCommands[idx].lMsgGen, pwszCommand );
}
}
m_nReturnValue = VSS_CMDRET_SUCCESS;
}
void CVssAdminCLI::AddDiffArea(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::AddDiffArea" );
// grab all of the options
VSS_ID ProviderId = GUID_NULL;
GetProviderId( &ProviderId );
LPWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
LPWSTR onVolume = GetOptionValueStr( VSSADM_O_ON );
LONGLONG llMaxSize;
if (!GetOptionValueNum( VSSADM_O_MAXSIZE, &llMaxSize ) )
llMaxSize = VSSADM_INFINITE_DIFFAREA;
// Verify the passed-in parameters
m_pVerifier->AddDiffArea (ProviderId, forVolume, onVolume, llMaxSize, ft);
// Create a Coordinator interface
CComPtr<IVssSnapshotMgmt> pIMgmt;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VssSnapshotMgmt,
L"VssSnapshotMgmt",
CLSCTX_ALL,
IID_IVssSnapshotMgmt,
(IUnknown**)&(pIMgmt));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
// Get the management object
CComPtr<IVssDifferentialSoftwareSnapshotMgmt> pIDiffSnapMgmt;
GetDifferentialSoftwareSnapshotMgmtInterface( ProviderId, pIMgmt, (IUnknown**)&pIDiffSnapMgmt );
// Now add the assocation
ft.hr = pIDiffSnapMgmt->AddDiffArea(forVolume, onVolume, llMaxSize );
if ( ft.HrFailed() )
{
switch( ft.hr )
{
case VSS_E_OBJECT_ALREADY_EXISTS:
OutputErrorMsg( MSG_ERROR_ASSOCIATION_ALREADY_EXISTS );
break;
default:
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"AddDiffArea failed with hr = 0x%08lx", ft.hr);
break;
}
return;
}
//
// Print results, if needed
//
OutputMsg( MSG_INFO_ADDED_DIFFAREA );
m_nReturnValue = VSS_CMDRET_SUCCESS;
}
void CVssAdminCLI::CreateSnapshot(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::CreateSnapshot" );
// Grab all parameters to the function
LONG lSnapshotContext = (dCurrentSKU & SKU_INT) ?
DetermineSnapshotType( GetOptionValueStr( VSSADM_O_SNAPTYPE ) ) :
VSS_CTX_CLIENT_ACCESSIBLE;
BS_ASSERT( lSnapshotContext | VSS_VOLSNAP_ATTR_NO_WRITERS );
LPWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
VSS_ID ProviderId = GUID_NULL;
GetProviderId( &ProviderId );
LONGLONG llTimeout = 0;
GetOptionValueNum (VSSADM_O_AUTORETRY, &llTimeout, false);
// Verify the passed-in parameters
m_pVerifier->CreateSnapshot (lSnapshotContext, forVolume, ProviderId, llTimeout, ft);
// Create the coordinator object
CComPtr<IVssCoordinator> pICoord;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VSSCoordinator,
L"Coordinator",
CLSCTX_ALL,
IID_IVssCoordinator,
(IUnknown**)&(pICoord));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
ft.hr = pICoord->SetContext(lSnapshotContext);
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error from SetContext(0x%x) hr = 0x%08lx", lSnapshotContext, ft.hr);
CComPtr<IVssAsync> pAsync;
VSS_ID SnapshotSetId = GUID_NULL;
// Starting a new snapshot set. Note, if another process is creating snapshots, then
// this will fail. If AutoRetry was specified, then retry the start snapshot set for
// that the specified number of minutes.
if (llTimeout > 0)
{
LARGE_INTEGER liPerfCount;
(void)QueryPerformanceCounter( &liPerfCount );
::srand( liPerfCount.LowPart );
DWORD dwTickcountStart = ::GetTickCount();
do
{
ft.hr = pICoord->StartSnapshotSet(&SnapshotSetId);
if ( ft.HrFailed() )
{
if ( ft.hr == VSS_E_SNAPSHOT_SET_IN_PROGRESS &&
( (LONGLONG)( ::GetTickCount() - dwTickcountStart ) < ( llTimeout * 1000 * 60 ) ) )
{
static dwMSec = 250; // Starting retry time
if ( dwMSec < 10000 )
{
dwMSec += ::rand() % 750;
}
ft.Trace( VSSDBG_VSSADMIN, L"Snapshot already in progress, retrying in %u millisecs", dwMSec );
Sleep( dwMSec );
}
else
{
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error from StartSnapshotSet hr = 0x%08lx", ft.hr);
}
}
} while ( ft.HrFailed() );
}
else
{
//
// Error right away with out a timeout when there is another snapshot in progress.
//
ft.hr = pICoord->StartSnapshotSet(&SnapshotSetId);
if ( ft.HrFailed() )
{
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error from StartSnapshotSet hr = 0x%08lx", ft.hr);
}
}
// Add the volume to the snapshot set
VSS_ID SnapshotId = GUID_NULL;
ft.hr = pICoord->AddToSnapshotSet(
forVolume,
ProviderId,
&SnapshotId);
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error from AddToSnapshotSet hr = 0x%08lx", ft.hr);
ft.hr = S_OK;
pAsync = NULL;
ft.hr = pICoord->DoSnapshotSet(NULL, &pAsync);
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr,
L"Error from DoSnapshotSet hr = 0x%08lx", ft.hr);
ft.hr = pAsync->Wait();
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr,
L"Error from Wait hr = 0x%08lx", ft.hr);
HRESULT hrStatus;
ft.hr = pAsync->QueryStatus(&hrStatus, NULL);
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr,
L"Error from QueryStatus hr = 0x%08lx", ft.hr);
//
// If VSS failed to create the snapshot, it's result code is in hrStatus. Process
// it.
//
ft.hr = hrStatus;
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr,
L"QueryStatus hrStatus parameter returned error, hr = 0x%08lx", ft.hr);
//
// Print results
//
VSS_SNAPSHOT_PROP sSSProp;
ft.hr = pICoord->GetSnapshotProperties( SnapshotId, &sSSProp );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr,
L"Error from GetId hr = 0x%08lx", ft.hr);
CVssAutoPWSZ awszSnapshotId( ::GuidToString( SnapshotId ) );
OutputMsg( MSG_INFO_SNAPSHOT_CREATED, forVolume,
(LPWSTR)awszSnapshotId, sSSProp.m_pwszSnapshotDeviceObject );
::VssFreeSnapshotProperties(&sSSProp);
m_nReturnValue = VSS_CMDRET_SUCCESS;
}
void CVssAdminCLI::DisplayDiffAreasPrivate(
IVssEnumMgmtObject *pIEnumMgmt
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DisplayDiffAreasPrivate" );
// For all diffareas do...
VSS_MGMT_OBJECT_PROP Prop;
VSS_DIFF_AREA_PROP& DiffArea = Prop.Obj.DiffArea;
for(;;)
{
// Get next element
ULONG ulFetched;
ft.hr = pIEnumMgmt->Next( 1, &Prop, &ulFetched );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
// Test if the cycle is finished
if (ft.hr == S_FALSE) {
BS_ASSERT( ulFetched == 0);
break;
}
CVssAutoPWSZ awszVolumeName( DiffArea.m_pwszVolumeName );
CVssAutoPWSZ awszDiffAreaVolumeName( DiffArea.m_pwszDiffAreaVolumeName );
CVssAutoPWSZ awszUsedSpace( FormatNumber( DiffArea.m_llUsedDiffSpace ) );
CVssAutoPWSZ awszAllocatedSpace( FormatNumber( DiffArea.m_llAllocatedDiffSpace ) );
CVssAutoPWSZ awszMaxSpace( FormatNumber( DiffArea.m_llMaximumDiffSpace ) );
LPCWSTR pwszVolumeDisplayName = GetVolumeDisplayName( awszVolumeName );
LPCWSTR pwszDiffAreaVolumeDisplayName = GetVolumeDisplayName( awszDiffAreaVolumeName );
OutputMsg( MSG_INFO_SNAPSHOT_STORAGE_CONTENTS,
pwszVolumeDisplayName,
(LPWSTR)awszVolumeName,
pwszDiffAreaVolumeDisplayName,
(LPWSTR)awszDiffAreaVolumeName,
(LPWSTR)awszUsedSpace,
(LPWSTR)awszAllocatedSpace,
(LPWSTR)awszMaxSpace
);
}
}
void CVssAdminCLI::ListDiffAreas(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ListDiffAreas" );
// Grab all parameters
VSS_ID ProviderId = GUID_NULL;
GetProviderId( &ProviderId );
LPWSTR forVolume = GetOptionValueStr (VSSADM_O_FOR);
LPWSTR onVolume = GetOptionValueStr (VSSADM_O_ON);
// Verify all parameters
m_pVerifier->ListDiffAreas (ProviderId, forVolume, onVolume, ft);
// Create a Coordinator interface
CComPtr<IVssSnapshotMgmt> pIMgmt;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VssSnapshotMgmt,
L"VssSnapshotMgmt",
CLSCTX_ALL,
IID_IVssSnapshotMgmt,
(IUnknown**)&(pIMgmt));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
// Get the management object
CComPtr<IVssDifferentialSoftwareSnapshotMgmt> pIDiffSnapMgmt;
GetDifferentialSoftwareSnapshotMgmtInterface( ProviderId, pIMgmt, (IUnknown**)&pIDiffSnapMgmt );
// See if query by for volume
if (forVolume != NULL )
{
// Query by For volume
CComPtr<IVssEnumMgmtObject> pIEnumMgmt;
ft.hr = pIDiffSnapMgmt->QueryDiffAreasForVolume(
forVolume,
&pIEnumMgmt );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryDiffAreasForVolume failed, hr = 0x%08lx", ft.hr);
if ( ft.hr == S_FALSE )
// empty query
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
L"CVssAdminCLI::ListDiffareas: No diffareas found that satisfy the query" );
DisplayDiffAreasPrivate( pIEnumMgmt );
}
else if (onVolume != NULL )
{
// Query by On volume
CComPtr<IVssEnumMgmtObject> pIEnumMgmt;
ft.hr = pIDiffSnapMgmt->QueryDiffAreasOnVolume(
onVolume,
&pIEnumMgmt );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryDiffAreasOnVolume failed, hr = 0x%08lx", ft.hr);
if ( ft.hr == S_FALSE )
// empty query
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
L"CVssAdminCLI::ListDiffareas: No diffareas found that satisfy the query" );
DisplayDiffAreasPrivate( pIEnumMgmt );
}
else
{
// Query all diff areas
BOOL bEmptyQuery = TRUE;
//
// Get the list of all volumes
//
CComPtr<IVssEnumMgmtObject> pIEnumMgmt;
ft.hr = pIMgmt->QueryVolumesSupportedForSnapshots(
ProviderId,
VSS_CTX_ALL,
&pIEnumMgmt );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryVolumesSupportedForSnapshots failed, hr = 0x%08lx", ft.hr);
if ( ft.hr == S_FALSE )
// empty query
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
L"CVssAdminCLI::ListDiffareas: No diffareas found that satisfy the query" );
//
// Query each volume to see if diff areas exist.
//
VSS_MGMT_OBJECT_PROP Prop;
VSS_VOLUME_PROP& VolProp = Prop.Obj.Vol;
for(;;)
{
// Get next element
ULONG ulFetched;
ft.hr = pIEnumMgmt->Next( 1, &Prop, &ulFetched );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
// Test if the cycle is finished
if (ft.hr == S_FALSE) {
BS_ASSERT( ulFetched == 0);
break;
}
CVssAutoPWSZ awszVolumeName( VolProp.m_pwszVolumeName );
CVssAutoPWSZ awszVolumeDisplayName( VolProp.m_pwszVolumeDisplayName );
// For all volumes do...
CComPtr<IVssEnumMgmtObject> pIEnumMgmtDiffArea;
ft.hr = pIDiffSnapMgmt->QueryDiffAreasForVolume(
awszVolumeName,
&pIEnumMgmtDiffArea );
if ( ft.HrFailed() )
{
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryDiffAreasForVolume failed, hr = 0x%08lx", ft.hr);
}
if ( ft.hr == S_FALSE )
{
// empty query
continue;
}
DisplayDiffAreasPrivate( pIEnumMgmtDiffArea );
bEmptyQuery = FALSE;
}
if ( bEmptyQuery )
// empty query
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
L"CVssAdminCLI::ListDiffareas: No diffareas found that satisfy the query" );
}
m_nReturnValue = VSS_CMDRET_SUCCESS;
}
void CVssAdminCLI::ListSnapshots(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ListSnapshots" );
// gather parameters
LONG lSnapshotContext = (dCurrentSKU & SKU_INT) ?
DetermineSnapshotType( GetOptionValueStr( VSSADM_O_SNAPTYPE ) ) :
VSS_CTX_ALL;
VSS_ID ProviderId = GUID_NULL;
GetProviderId( &ProviderId );
LPCWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
bool bNonEmptyResult = false;
// --- get the set id
VSS_ID guidSSID = GUID_NULL;
if ( GetOptionValueStr( VSSADM_O_SET ) != NULL &&
!ScanGuid( GetOptionValueStr( VSSADM_O_SET ), guidSSID ))
{
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_INVALID_OPTION_VALUE,
L"CVssAdminCLI::ListSnapshots: invalid snapshot set ID: %s",
GetOptionValueStr( VSSADM_O_SET ) );
}
// --- get the snapshot id
VSS_ID guidSnapID = GUID_NULL;
if ( GetOptionValueStr( VSSADM_O_SNAPSHOT ) != NULL &&
!ScanGuid( GetOptionValueStr( VSSADM_O_SNAPSHOT ), guidSnapID ))
{
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_INVALID_OPTION_VALUE,
L"CVssAdminCLI::ListSnapshots: invalid snapshot ID: %s",
GetOptionValueStr( VSSADM_O_SNAPSHOT ) );
}
// verify the parameters
m_pVerifier->ListSnapshots (lSnapshotContext, ProviderId, forVolume, guidSnapID, guidSSID, ft);
// See if we have to filter by volume name
WCHAR wszVolumeNameInternal[x_nLengthOfVolMgmtVolumeName + 1] = L"";
if (forVolume != NULL )
{
// Calculate the unique volume name, just to make sure that we have the right path
// If FOR volume name starts with the '\', assume it is already in the correct volume name format.
// This is important for transported volumes since GetVolumeNameForVolumeMountPointW() won't work.
if ( forVolume[0] != L'\\' )
{
if (!::GetVolumeNameForVolumeMountPointW(forVolume,
wszVolumeNameInternal, ARRAY_LEN(wszVolumeNameInternal)))
ft.Throw( VSSDBG_COORD, VSS_E_OBJECT_NOT_FOUND,
L"GetVolumeNameForVolumeMountPoint(%s,...) "
L"failed with error code 0x%08lx", forVolume, ::GetLastError());
}
else
{
::wcsncpy( wszVolumeNameInternal, forVolume, STRING_LEN(wszVolumeNameInternal) );
wszVolumeNameInternal[x_nLengthOfVolMgmtVolumeName] = L'\0';
}
}
//
// See if we have to filter by provider
//
// Query the snapshots
CVssAdmSnapshotSets cVssAdmSS;
cVssAdmSS.Initialize( lSnapshotContext, guidSSID, guidSnapID, ProviderId, wszVolumeNameInternal );
INT iSnapshotSetCount = cVssAdmSS.GetSnapshotSetCount();
// If there are no present snapshots then display a message.
if (iSnapshotSetCount == 0) {
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
L"CVssAdminCLI::ListSnapshots: No snapshots found that satisfy the query");
}
// For all snapshot sets do...
for ( INT iSSS = 0; iSSS < iSnapshotSetCount; ++iSSS )
{
CVssAdmSnapshotSetEntry *pcSSE;
pcSSE = cVssAdmSS.GetSnapshotSetAt( iSSS );
BS_ASSERT( pcSSE != NULL );
CVssAutoPWSZ awszGuid( ::GuidToString( pcSSE->GetSnapshotSetId() ) ) ;
CVssAutoPWSZ awszDateTime( ::DateTimeToString( &( pcSSE->GetSnapshotAt( 0 )->m_tsCreationTimestamp ) ) );
// Print each snapshot set
OutputMsg(
MSG_INFO_SNAPSHOT_SET_HEADER,
(LPWSTR)awszGuid,
pcSSE->GetOriginalSnapshotCount(),
(LPWSTR)awszDateTime );
INT iSnapshotCount = pcSSE->GetSnapshotCount();
VSS_SNAPSHOT_PROP *pSnap;
for( INT iSS = 0; iSS < iSnapshotCount; ++iSS ) {
pSnap = pcSSE->GetSnapshotAt( iSS );
BS_ASSERT( pSnap != NULL );
// Get the provider name
LPCWSTR pwszProviderName = GetProviderName( pSnap->m_ProviderId );
CVssAutoPWSZ awszAttributeStr( BuildSnapshotAttributeDisplayString( pSnap->m_lSnapshotAttributes ) );
CVssAutoPWSZ awszSnapshotType( DetermineSnapshotType( pSnap->m_lSnapshotAttributes ) );
// Print each snapshot
CVssAutoPWSZ awszSnapGuid( ::GuidToString( pSnap->m_SnapshotId ) );
LPCWSTR pwszVolumeDisplayName = GetVolumeDisplayName( pSnap->m_pwszOriginalVolumeName );
OutputMsg(
MSG_INFO_SNAPSHOT_CONTENTS,
(LPWSTR)awszSnapGuid,
pwszVolumeDisplayName ? pwszVolumeDisplayName : L"?",
pSnap->m_pwszOriginalVolumeName,
pSnap->m_pwszSnapshotDeviceObject,
pSnap->m_pwszOriginatingMachine ? pSnap->m_pwszOriginatingMachine : L"",
pSnap->m_pwszServiceMachine ? pSnap->m_pwszServiceMachine : L"", // fix this when the idl file changes
pwszProviderName ? pwszProviderName : L"?",
(LPWSTR)awszSnapshotType,
(LPWSTR)awszAttributeStr
);
bNonEmptyResult = true;
}
}
m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
}
void CVssAdminCLI::DumpSnapshotTypes(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DumpSnapshotTypes" );
//
// Dump list of snapshot types based on SKU
//
INT idx;
// Determine type of snapshot
for ( idx = 0; g_asAdmTypeNames[idx].pwszName != NULL; ++idx )
{
if ( dCurrentSKU & g_asAdmTypeNames[idx].dwSKUs )
{
OutputMsg (g_asAdmTypeNames[idx].pwszDescription,
g_asAdmTypeNames[idx].pwszName);
}
}
}
void CVssAdminCLI::ListWriters(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ListWriters" );
// verify the parameters
m_pVerifier->ListWriters (ft);
bool bNonEmptyResult = false;
// Get the backup components object
CComPtr<IVssBackupComponents> pBackupComp;
CComPtr<IVssAsync> pAsync;
ft.hr = ::CreateVssBackupComponents(&pBackupComp);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"CreateVssBackupComponents failed with hr = 0x%08lx", ft.hr);
ft.hr = pBackupComp->InitializeForBackup();
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"InitializeForBackup failed with hr = 0x%08lx", ft.hr);
UINT unWritersCount;
// get metadata for all writers
ft.hr = pBackupComp->GatherWriterMetadata(&pAsync);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"GatherWriterMetadata failed with hr = 0x%08lx", ft.hr);
// Using polling, try to obtain the list of writers as soon as possible
HRESULT hrReturned = S_OK;
for (int nRetries = 0; nRetries < x_nMaxRetriesCount; nRetries++ ) {
// Wait a little
::Sleep(x_nPollingInterval);
// Check if finished
INT nReserved = 0;
ft.hr = pAsync->QueryStatus(
&hrReturned,
&nReserved
);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr,
L"IVssAsync::QueryStatus failed with hr = 0x%08lx", ft.hr);
if (hrReturned == VSS_S_ASYNC_FINISHED)
break;
if (hrReturned == VSS_S_ASYNC_PENDING)
continue;
ft.Throw( VSSDBG_VSSADMIN, ft.hr,
L"IVssAsync::QueryStatus returned hr = 0x%08lx", hrReturned);
}
// If still not ready, then print the "waiting for responses" message and wait.
if (hrReturned == VSS_S_ASYNC_PENDING) {
OutputMsg( MSG_INFO_WAITING_RESPONSES );
ft.hr = pAsync->Wait();
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"IVssAsync::Wait failed with hr = 0x%08lx", ft.hr);
}
pAsync = NULL;
// Free the writer metadata
ft.hr = pBackupComp->FreeWriterMetadata();
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"FreeWriterMetadata failed with hr = 0x%08lx", ft.hr);
// Gather the status of all writers
ft.hr = pBackupComp->GatherWriterStatus(&pAsync);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"GatherWriterStatus failed with hr = 0x%08lx", ft.hr);
ft.hr = pAsync->Wait();
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"IVssAsync::Wait failed with hr = 0x%08lx", ft.hr);
pAsync = NULL;
ft.hr = pBackupComp->GetWriterStatusCount(&unWritersCount);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"GetWriterStatusCount failed with hr = 0x%08lx", ft.hr);
// Print each writer status+supplementary info
for(UINT unIndex = 0; unIndex < unWritersCount; unIndex++)
{
VSS_ID idInstance = GUID_NULL;
VSS_ID idWriter = GUID_NULL;
CComBSTR bstrWriter;
VSS_WRITER_STATE eStatus;
HRESULT hrWriterFailure;
// Get the status for the (unIndex)-th writer
ft.hr = pBackupComp->GetWriterStatus(unIndex, &idInstance, &idWriter, &bstrWriter, &eStatus, &hrWriterFailure);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"GetWriterStatus failed with hr = 0x%08lx", ft.hr);
// Get the status description strings
LPCWSTR pwszStatusDescription;
switch (eStatus)
{
case VSS_WS_STABLE:
pwszStatusDescription = LoadString( IDS_WRITER_STATUS_STABLE);
break;
case VSS_WS_WAITING_FOR_FREEZE:
pwszStatusDescription = LoadString( IDS_WRITER_STATUS_WAITING_FOR_FREEZE);
break;
case VSS_WS_WAITING_FOR_THAW:
pwszStatusDescription = LoadString( IDS_WRITER_STATUS_FROZEN);
break;
case VSS_WS_WAITING_FOR_POST_SNAPSHOT:
pwszStatusDescription = LoadString( IDS_WRITER_STATUS_WAITING_FOR_POST_SNAPSHOT);
break;
case VSS_WS_WAITING_FOR_BACKUP_COMPLETE:
pwszStatusDescription = LoadString( IDS_WRITER_STATUS_WAITING_FOR_COMPLETION);
break;
case VSS_WS_FAILED_AT_IDENTIFY:
case VSS_WS_FAILED_AT_PREPARE_BACKUP:
case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT:
case VSS_WS_FAILED_AT_FREEZE:
case VSS_WS_FAILED_AT_THAW:
case VSS_WS_FAILED_AT_POST_SNAPSHOT:
case VSS_WS_FAILED_AT_BACKUP_COMPLETE:
case VSS_WS_FAILED_AT_PRE_RESTORE:
case VSS_WS_FAILED_AT_POST_RESTORE:
pwszStatusDescription = LoadString( IDS_WRITER_STATUS_FAILED);
break;
default:
pwszStatusDescription = LoadString( IDS_WRITER_STATUS_UNKNOWN);
break;
}
BS_ASSERT(pwszStatusDescription);
LPCWSTR pwszWriterError;
switch ( hrWriterFailure )
{
case S_OK:
pwszWriterError = LoadString ( IDS_WRITER_ERROR_SUCCESS );
break;
case VSS_E_WRITER_NOT_RESPONDING:
pwszWriterError = LoadString( IDS_WRITER_ERROR_NOT_RESPONDING );
break;
case VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT:
pwszWriterError = LoadString( IDS_WRITER_ERROR_INCONSISTENTSNAPSHOT);
break;
case VSS_E_WRITERERROR_OUTOFRESOURCES:
pwszWriterError = LoadString( IDS_WRITER_ERROR_OUTOFRESOURCES);
break;
case VSS_E_WRITERERROR_TIMEOUT:
pwszWriterError = LoadString( IDS_WRITER_ERROR_TIMEOUT);
break;
case VSS_E_WRITERERROR_RETRYABLE:
pwszWriterError = LoadString( IDS_WRITER_ERROR_RETRYABLE);
break;
case VSS_E_WRITERERROR_NONRETRYABLE:
pwszWriterError = LoadString( IDS_WRITER_ERROR_NONRETRYABLE);
break;
default:
pwszWriterError = LoadString( IDS_WRITER_ERROR_UNEXPECTED);
ft.Trace( VSSDBG_VSSADMIN, L"Unexpected writer error failure: 0x%08x", hrWriterFailure );
break;
}
CVssAutoPWSZ awszWriterId( ::GuidToString( idWriter ) );
CVssAutoPWSZ awszInstanceId( ::GuidToString( idInstance ) );
OutputMsg( MSG_INFO_WRITER_CONTENTS,
(LPWSTR)bstrWriter ? (LPWSTR)bstrWriter : L"",
(LPWSTR)awszWriterId,
(LPWSTR)awszInstanceId,
(INT)eStatus,
pwszStatusDescription,
pwszWriterError
);
bNonEmptyResult = true;
}
ft.hr = pBackupComp->FreeWriterStatus();
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"FreeWriterStatus failed with hr = 0x%08lx", ft.hr);
m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
}
void CVssAdminCLI::ListProviders(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ListProviders" );
// verify the parameters
m_pVerifier->ListProviders (ft);
bool bNonEmptyResult = false;
// Create the coordinator object
CComPtr<IVssCoordinator> pICoord;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VSSCoordinator,
L"Coordinator",
CLSCTX_ALL,
IID_IVssCoordinator,
(IUnknown**)&(pICoord));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
// Query all (filtered) snapshot sets
CComPtr<IVssEnumObject> pIEnumProv;
ft.hr = pICoord->Query( GUID_NULL,
VSS_OBJECT_NONE,
VSS_OBJECT_PROVIDER,
&pIEnumProv );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Query failed with hr = 0x%08lx", ft.hr);
// For all snapshot sets do...
VSS_OBJECT_PROP Prop;
VSS_PROVIDER_PROP& Prov = Prop.Obj.Prov;
for(;;) {
// Get next element
ULONG ulFetched;
ft.hr = pIEnumProv->Next( 1, &Prop, &ulFetched );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
// Test if the cycle is ended
if (ft.hr == S_FALSE) {
BS_ASSERT( ulFetched == 0);
break;
}
// Get the provider type strings
LPCWSTR pwszProviderType;
switch (Prov.m_eProviderType) {
case VSS_PROV_SYSTEM:
pwszProviderType = LoadString( IDS_PROV_TYPE_SYSTEM);
break;
case VSS_PROV_SOFTWARE:
pwszProviderType = LoadString( IDS_PROV_TYPE_SOFTWARE);
break;
case VSS_PROV_HARDWARE:
pwszProviderType = LoadString( IDS_PROV_TYPE_HARDWARE);
break;
default:
pwszProviderType = LoadString( IDS_PROV_TYPE_UNKNOWN);
break;
}
BS_ASSERT(pwszProviderType);
// Print each snapshot set
CVssAutoPWSZ awszProviderId( ::GuidToString( Prov.m_ProviderId ) );
CVssAutoPWSZ awszProviderName( Prov.m_pwszProviderName );
CVssAutoPWSZ awszProviderVersion( Prov.m_pwszProviderVersion );
OutputMsg( MSG_INFO_PROVIDER_CONTENTS,
(LPWSTR)awszProviderName ? (LPWSTR)awszProviderName: L"",
pwszProviderType,
(LPWSTR)awszProviderId,
(LPWSTR)awszProviderVersion ? (LPWSTR)awszProviderVersion: L"");
bNonEmptyResult = true;
}
m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
}
void CVssAdminCLI::ListVolumes(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ListVolumes" );
// gather the parameters
LONG lContext = (dCurrentSKU & SKU_INT) ?
DetermineSnapshotType( GetOptionValueStr( VSSADM_O_SNAPTYPE ) ) :
VSS_CTX_CLIENT_ACCESSIBLE;
VSS_ID ProviderId = GUID_NULL;
GetProviderId( &ProviderId );
// verify the parameters
m_pVerifier->ListVolumes (ProviderId, lContext, ft);
// Create a Coordinator interface
CComPtr<IVssSnapshotMgmt> pIMgmt;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VssSnapshotMgmt,
L"VssSnapshotMgmt",
CLSCTX_ALL,
IID_IVssSnapshotMgmt,
(IUnknown**)&(pIMgmt));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
//
// Get the list of all volumes
//
CComPtr<IVssEnumMgmtObject> pIEnumMgmt;
ft.hr = pIMgmt->QueryVolumesSupportedForSnapshots(
ProviderId,
lContext,
&pIEnumMgmt );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryVolumesSupportedForSnapshots failed, hr = 0x%08lx", ft.hr);
if ( ft.hr == S_FALSE )
// empty query
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
L"CVssAdminCLI::ListVolumes: No volumes found that satisfy the query" );
//
// Query each volume to see if diff areas exist.
//
VSS_MGMT_OBJECT_PROP Prop;
VSS_VOLUME_PROP& VolProp = Prop.Obj.Vol;
for(;;)
{
// Get next element
ULONG ulFetched;
ft.hr = pIEnumMgmt->Next( 1, &Prop, &ulFetched );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
// Test if the cycle is finished
if (ft.hr == S_FALSE) {
BS_ASSERT( ulFetched == 0);
break;
}
CVssAutoPWSZ awszVolumeName( VolProp.m_pwszVolumeName );
CVssAutoPWSZ awszVolumeDisplayName( VolProp.m_pwszVolumeDisplayName );
OutputMsg( MSG_INFO_VOLUME_CONTENTS, (LPWSTR)awszVolumeDisplayName, (LPWSTR)awszVolumeName );
}
m_nReturnValue = VSS_CMDRET_SUCCESS;
}
void CVssAdminCLI::ResizeDiffArea(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ResizeDiffArea" );
// gather the parameters
VSS_ID ProviderId = GUID_NULL;
GetProviderId( &ProviderId );
LPWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
LPWSTR onVolume = GetOptionValueStr( VSSADM_O_ON );
LONGLONG llMaxSize = 0;
if (!GetOptionValueNum( VSSADM_O_MAXSIZE, &llMaxSize ))
{
llMaxSize = VSSADM_INFINITE_DIFFAREA;
}
// verify the parameters
m_pVerifier->ResizeDiffArea (ProviderId, forVolume, onVolume, llMaxSize, ft);
// Create a Coordinator interface
CComPtr<IVssSnapshotMgmt> pIMgmt;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VssSnapshotMgmt,
L"VssSnapshotMgmt",
CLSCTX_ALL,
IID_IVssSnapshotMgmt,
(IUnknown**)&(pIMgmt));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
// Get the management object
CComPtr<IVssDifferentialSoftwareSnapshotMgmt> pIDiffSnapMgmt;
GetDifferentialSoftwareSnapshotMgmtInterface( ProviderId, pIMgmt, (IUnknown**)&pIDiffSnapMgmt );
// Now add the assocation
ft.hr = pIDiffSnapMgmt->ChangeDiffAreaMaximumSize(forVolume, onVolume, llMaxSize );
if ( ft.HrFailed() )
{
if ( ft.hr == VSS_E_OBJECT_NOT_FOUND ) // should be VSS_E_MAXIMUM_DIFFAREA_ASSOCIATIONS
{
// The associations was not found
OutputErrorMsg( MSG_ERROR_ASSOCIATION_NOT_FOUND );
return;
}
else
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"ResizeDiffArea failed with hr = 0x%08lx", ft.hr);
}
//
// Print results, if needed
//
OutputMsg( MSG_INFO_RESIZED_DIFFAREA );
m_nReturnValue = VSS_CMDRET_SUCCESS;
}
void CVssAdminCLI::DeleteDiffAreas(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DeleteDiffAreas" );
// gather the parameters
VSS_ID ProviderId = GUID_NULL;
GetProviderId( &ProviderId );
LPWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
LPWSTR onVolume = GetOptionValueStr( VSSADM_O_ON );
// verify the parameters
m_pVerifier->DeleteDiffAreas (ProviderId, forVolume, onVolume, IsQuiet() == TRUE, ft);
// Create a Coordinator interface
CComPtr<IVssSnapshotMgmt> pIMgmt;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VssSnapshotMgmt,
L"VssSnapshotMgmt",
CLSCTX_ALL,
IID_IVssSnapshotMgmt,
(IUnknown**)&(pIMgmt));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
// Get the management object
CComPtr<IVssDifferentialSoftwareSnapshotMgmt> pIDiffSnapMgmt;
GetDifferentialSoftwareSnapshotMgmtInterface( ProviderId, pIMgmt, (IUnknown**)&pIDiffSnapMgmt );
//
// See if the on option was provided. If not, determine what the on value is:
//
CVssAutoPWSZ awszOnVol;
if (onVolume == NULL )
{
// Need to query the association to get the on value...
CComPtr<IVssEnumMgmtObject> pIEnumMgmt;
ft.hr = pIDiffSnapMgmt->QueryDiffAreasForVolume(
forVolume,
&pIEnumMgmt );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryDiffAreasForVolume failed, hr = 0x%08lx", ft.hr);
if ( ft.hr == S_FALSE )
{
// empty query
OutputErrorMsg( MSG_ERROR_ASSOCIATION_NOT_FOUND );
return;
}
VSS_MGMT_OBJECT_PROP Prop;
VSS_DIFF_AREA_PROP& DiffArea = Prop.Obj.DiffArea;
// Get next element
ULONG ulFetched;
ft.hr = pIEnumMgmt->Next( 1, &Prop, &ulFetched );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
// Test if the cycle is finished
if (ft.hr == S_FALSE)
{
OutputErrorMsg( MSG_ERROR_ASSOCIATION_NOT_FOUND );
return;
}
::VssFreeString( DiffArea.m_pwszVolumeName );
CVssAutoPWSZ awszDiffAreaVolumeName( DiffArea.m_pwszDiffAreaVolumeName );
// Save it away in the auto delete object.
awszOnVol.CopyFrom( awszDiffAreaVolumeName );
onVolume = awszOnVol;
}
// Now delete the assocation by changing the size to zero
ft.hr = pIDiffSnapMgmt->ChangeDiffAreaMaximumSize(
forVolume,
onVolume,
0 );
if ( ft.HrFailed() )
{
if ( ft.hr == VSS_E_OBJECT_NOT_FOUND ) // should be VSS_E_MAXIMUM_DIFFAREA_ASSOCIATIONS
{
// The associations was not found
OutputErrorMsg( MSG_ERROR_ASSOCIATION_NOT_FOUND );
return;
}
else if ( ft.hr == VSS_E_VOLUME_IN_USE )
{
// Can't delete associations that are in use
OutputErrorMsg( MSG_ERROR_ASSOCIATION_IS_IN_USE );
return;
}
else
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"ResizeDiffArea to 0 failed with hr = 0x%08lx", ft.hr);
}
//
// Print results, if needed
//
if ( !IsQuiet() )
{
OutputMsg( MSG_INFO_DELETED_DIFFAREAS );
}
m_nReturnValue = VSS_CMDRET_SUCCESS;
}
void CVssAdminCLI::DeleteSnapshots(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DeleteSnapshots" );
// gather the parameters
LONG lContext = (dCurrentSKU & SKU_INT) ?
DetermineSnapshotType( GetOptionValueStr( VSSADM_O_SNAPTYPE ) ) :
VSS_CTX_CLIENT_ACCESSIBLE;
LPCWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
BOOL oldest = GetOptionValueBool( VSSADM_O_OLDEST );
BOOL all = GetOptionValueBool(VSSADM_O_ALL);
VSS_ID SnapshotId = GUID_NULL;
if (GetOptionValueStr (VSSADM_O_SNAPSHOT) &&
!ScanGuid (GetOptionValueStr (VSSADM_O_SNAPSHOT), SnapshotId))
{
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_INVALID_OPTION_VALUE,
L"CVssAdminCLI::DeleteSnapshots: Invalid snapshot id" );
}
// verify the parameters
m_pVerifier->DeleteSnapshots (lContext, forVolume, all == TRUE, oldest==TRUE, SnapshotId, IsQuiet()==TRUE, ft);
LONG lNumDeleted = 0;
if ( GetOptionValueStr( VSSADM_O_SNAPSHOT ) )
{
//
// Let's try to delete the snapshot
//
if ( PromptUserForConfirmation( MSG_INFO_PROMPT_USER_FOR_DELETE_SNAPSHOTS, 1 ) )
{
// Create the coordinator object
CComPtr<IVssCoordinator> pICoord;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VSSCoordinator,
L"Coordinator",
CLSCTX_ALL,
IID_IVssCoordinator,
(IUnknown**)&(pICoord));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
// Set all context
ft.hr = pICoord->SetContext( lContext );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"SetContext failed with hr = 0x%08lx", ft.hr);
VSS_ID NondeletedSnapshotId = GUID_NULL;
ft.hr = pICoord->DeleteSnapshots(
SnapshotId,
VSS_OBJECT_SNAPSHOT,
TRUE,
&lNumDeleted,
&NondeletedSnapshotId );
if ( ft.hr == VSS_E_OBJECT_NOT_FOUND )
{
OutputErrorMsg( MSG_ERROR_SNAPSHOT_NOT_FOUND, GetOptionValueStr( VSSADM_O_SNAPSHOT ) );
}
else if ( ft.HrFailed() )
{
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"DeleteSnapshots failed with hr = 0x%08lx", ft.hr);
}
}
}
else
{
BS_ASSERT (GetOptionValueStr(VSSADM_O_SNAPSHOT) == NULL);
// Calculate the unique volume name, just to make sure that we have the right path
WCHAR wszVolumeNameInternal[x_nLengthOfVolMgmtVolumeName + 1];
memset (wszVolumeNameInternal, 0, sizeof(wszVolumeNameInternal));
// If FOR volume name starts with the '\', assume it is already in the correct volume name format.
// This is important for transported volumes since GetVolumeNameForVolumeMountPointW() won't work.
if (forVolume != NULL && forVolume[0] != L'\\' )
{
if (!::GetVolumeNameForVolumeMountPointW( forVolume,
wszVolumeNameInternal, ARRAY_LEN(wszVolumeNameInternal)))
ft.Throw( VSSDBG_COORD, VSS_E_OBJECT_NOT_FOUND,
L"GetVolumeNameForVolumeMountPoint(%s,...) "
L"failed with error code 0x%08lx", GetOptionValueStr( VSSADM_O_FOR ), ::GetLastError());
}
else if (forVolume != NULL)
{
::wcsncpy( wszVolumeNameInternal, forVolume, STRING_LEN(wszVolumeNameInternal) );
wszVolumeNameInternal[x_nLengthOfVolMgmtVolumeName] = L'\0';
}
// Create the coordinator object
CComPtr<IVssCoordinator> pICoord;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VSSCoordinator,
L"Coordinator",
CLSCTX_ALL,
IID_IVssCoordinator,
(IUnknown**)&(pICoord));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
// Set the context
ft.hr = pICoord->SetContext( lContext);
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"SetContext failed with hr = 0x%08lx", ft.hr);
// Get list all snapshots
CComPtr<IVssEnumObject> pIEnumSnapshots;
ft.hr = pICoord->Query( GUID_NULL,
VSS_OBJECT_NONE,
VSS_OBJECT_SNAPSHOT,
&pIEnumSnapshots );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Query failed with hr = 0x%08lx", ft.hr);
// For all snapshots do...
VSS_ID OldestSnapshotId = GUID_NULL; // used if Oldest option is specified
VSS_TIMESTAMP OldestSnapshotTimestamp = 0x7FFFFFFFFFFFFFFF; // Used if Oldest option is specified
VSS_OBJECT_PROP Prop;
//
// If not asking to delete the oldest snapshot, this could possibly delete multiple snapshots
// Let's determine how many snapshots will be deleted. If one or more, ask the user if we
// should continue. If in quiet mode, don't bother the user and skip this step.
//
if ( !oldest && !IsQuiet() )
{
ULONG ulNumToBeDeleted = 0;
for (;;)
{
ULONG ulFetched;
ft.hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
// Test if the cycle is finished
if (ft.hr == S_FALSE) {
BS_ASSERT( ulFetched == 0);
break;
}
// Use auto delete class to manage the snapshot properties
CVssAutoSnapshotProperties cSnap( Prop );
if (::_wcsicmp( cSnap->m_pwszOriginalVolumeName, wszVolumeNameInternal ) == 0 ||
(forVolume == NULL && all))
++ulNumToBeDeleted;
}
if ( ulNumToBeDeleted == 0 )
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
L"CVssAdminCLI::DeleteSnapshots: No snapshots found that satisfy the query");
if ( !PromptUserForConfirmation( MSG_INFO_PROMPT_USER_FOR_DELETE_SNAPSHOTS, ulNumToBeDeleted ) )
return;
// Reset the enumerator to the beginning.
ft.hr = pIEnumSnapshots->Reset();
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Reset failed with hr = 0x%08lx", ft.hr);
}
//
// Now iterate through the list of snapshots looking for matches and delete them.
//
for(;;)
{
// Get next element
ULONG ulFetched;
ft.hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
// Test if the cycle is finished
if (ft.hr == S_FALSE) {
BS_ASSERT( ulFetched == 0);
break;
}
// Use auto delete class to manage the snapshot properties
CVssAutoSnapshotProperties cSnap( Prop );
if (::_wcsicmp( cSnap->m_pwszOriginalVolumeName, wszVolumeNameInternal ) == 0 ||
(forVolume == NULL && all))
{
// We have a volume name match
if (oldest)
{
// Stow away snapshot info if this is the oldest one so far
if ( OldestSnapshotTimestamp > cSnap->m_tsCreationTimestamp )
{
OldestSnapshotId = cSnap->m_SnapshotId;
OldestSnapshotTimestamp = cSnap->m_tsCreationTimestamp;
}
}
else
{
// Delete the snapshot
VSS_ID NondeletedSnapshotId = GUID_NULL;
LONG lNumDeletedPrivate;
ft.hr = pICoord->DeleteSnapshots(
cSnap->m_SnapshotId,
VSS_OBJECT_SNAPSHOT,
TRUE,
&lNumDeletedPrivate,
&NondeletedSnapshotId );
if ( ft.HrFailed() )
{
// If it is object not found, the snapshot must have gotten deleted by someone else
if ( ft.hr != VSS_E_OBJECT_NOT_FOUND )
{
// Print out an error message but keep going
CVssAutoPWSZ awszSnapshotId( ::GuidToString( cSnap->m_SnapshotId ) );
OutputErrorMsg( MSG_ERROR_UNABLE_TO_DELETE_SNAPSHOT, ft.hr, (LPWSTR)awszSnapshotId );
}
}
else
{
lNumDeleted += lNumDeletedPrivate;
}
}
}
}
// If in delete oldest mode, do the delete
if (oldest && OldestSnapshotId != GUID_NULL )
{
if ( PromptUserForConfirmation( MSG_INFO_PROMPT_USER_FOR_DELETE_SNAPSHOTS, 1 ) )
{
// Delete the snapshot
VSS_ID NondeletedSnapshotId = GUID_NULL;
ft.hr = pICoord->DeleteSnapshots(
OldestSnapshotId,
VSS_OBJECT_SNAPSHOT,
TRUE,
&lNumDeleted,
&NondeletedSnapshotId );
if ( ft.HrFailed() )
{
CVssAutoPWSZ awszSnapshotId( ::GuidToString( OldestSnapshotId ) );
// If it is object not found, the snapshot must have gotten deleted by someone else
if ( ft.hr == VSS_E_OBJECT_NOT_FOUND )
{
OutputErrorMsg( MSG_ERROR_SNAPSHOT_NOT_FOUND, awszSnapshotId );
}
else
{
OutputErrorMsg( MSG_ERROR_UNABLE_TO_DELETE_SNAPSHOT, ft.hr, awszSnapshotId );
}
}
}
else
return;
}
if ( lNumDeleted == 0 )
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
L"CVssAdminCLI::DeleteSnapshots: No snapshots found that satisfy the query");
}
if ( !IsQuiet() && lNumDeleted > 0 )
OutputMsg( MSG_INFO_SNAPSHOTS_DELETED_SUCCESSFULLY, lNumDeleted );
m_nReturnValue = VSS_CMDRET_SUCCESS;
}
void CVssAdminCLI::ExposeSnapshot(
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ExposeSnapshot" );
// gather the parameters
BOOL bExposeLocally = FALSE;
LPWSTR pwszExposeUsing = GetOptionValueStr( VSSADM_O_EXPOSE_USING );
LPWSTR pwszPathFromRoot = GetOptionValueStr( VSSADM_O_SHAREPATH );
if ( pwszExposeUsing != NULL && ::wcslen( pwszExposeUsing ) >= 2 && pwszExposeUsing[1] == L':' )
{
// User specified a mountpoint or a drive letter.
bExposeLocally = TRUE;
}
BS_ASSERT (GetOptionValueStr (VSSADM_O_SNAPSHOT) != NULL);
VSS_ID SnapshotId = GUID_NULL;
if (!ScanGuid (GetOptionValueStr (VSSADM_O_SNAPSHOT), SnapshotId))
{
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_INVALID_OPTION_VALUE,
L"CVssAdminCLI::ExposeSnapshot: Invalid snapshot id" );
}
// verify the parameters
m_pVerifier->ExposeSnapshot (SnapshotId, pwszExposeUsing, pwszPathFromRoot, bExposeLocally==TRUE, ft);
LONG lAttributes;
if ( bExposeLocally )
lAttributes = VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY;
else
lAttributes = VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY;
// Create the coordinator object
CComPtr<IVssCoordinator> pICoord;
ft.CoCreateInstanceWithLog(
VSSDBG_VSSADMIN,
CLSID_VSSCoordinator,
L"Coordinator",
CLSCTX_ALL,
IID_IVssCoordinator,
(IUnknown**)&(pICoord));
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
// Set the context to all so that we don't have to specify a specific context which would require either
// the user to specify it on the command-line or for us to first query the snapshot to determine its
// context.
ft.hr = pICoord->SetContext( VSS_CTX_ALL );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error returned from IVssCoordinator::SetContext( CTX_ALL) hr = 0x%08x", ft.hr);
LPWSTR wszExposedAs = NULL;
// Now try to expose
ft.hr = pICoord->ExposeSnapshot( SnapshotId,
pwszPathFromRoot,
lAttributes,
pwszExposeUsing,
&wszExposedAs );
if ( ft.HrFailed() )
{
switch (ft.hr) {
case E_INVALIDARG:
OutputErrorMsg( MSG_ERROR_EXPOSE_INVALID_ARG);
return;
case VSS_E_OBJECT_ALREADY_EXISTS:
OutputErrorMsg(MSG_ERROR_EXPOSE_OBJECT_EXISTS);
return;
case VSS_E_OBJECT_NOT_FOUND:
OutputErrorMsg( MSG_ERROR_SNAPSHOT_NOT_FOUND, GetOptionValueStr( VSSADM_O_SNAPSHOT ) );
return;
default:
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error returned from ExposeSnapshot: hr = 0x%08x", ft.hr);
}
}
CVssAutoPWSZ awszExposedAs( wszExposedAs );
// The snapshot is exposed, print the results to the user
OutputMsg( MSG_INFO_EXPOSE_SNAPSHOT_SUCCESSFUL, awszExposedAs );
m_nReturnValue = VSS_CMDRET_SUCCESS;
}
LPWSTR CVssAdminCLI::BuildSnapshotAttributeDisplayString(
IN DWORD Attr
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::BuildSnapshotAttributeDisplayString" );
WCHAR pwszDisplayString[1024] = L"";
WORD wBit = 0;
// Go through the bits of the attribute
for ( ; wBit < (sizeof ( Attr ) * 8) ; ++wBit )
{
switch ( Attr & ( 1 << wBit ) )
{
case 0:
break;
case VSS_VOLSNAP_ATTR_PERSISTENT:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_PERSISTENT, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_CLIENT_ACCESSIBLE:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_CLIENT_ACCESSIBLE, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_NO_AUTO_RELEASE:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_NO_AUTO_RELEASE, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_NO_WRITERS:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_NO_WRITERS, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_TRANSPORTABLE:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_TRANSPORTABLE, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_NOT_SURFACED:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_NOT_SURFACED, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_HARDWARE_ASSISTED:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_HARDWARE_ASSISTED, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_DIFFERENTIAL:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_DIFFERENTIAL, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_PLEX:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_PLEX, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_IMPORTED:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_IMPORTED, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_EXPOSED_LOCALLY, 0, L", " );
break;
case VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_EXPOSED_REMOTELY, 0, L", " );
break;
default:
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
0, Attr & ( 1 << wBit ), L", " );
break;
}
}
// If this is a backup snapshot, most like there will not be any attributes
if ( pwszDisplayString[0] == L'\0' )
{
AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
MSG_INFO_SNAPSHOT_ATTR_NONE, 0, L", " );
}
LPWSTR pwszRetString = NULL;
::VssSafeDuplicateStr( ft, pwszRetString, pwszDisplayString );
return pwszRetString;
}
LONG CVssAdminCLI::DetermineSnapshotType(
IN LPCWSTR pwszType
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DetermineSnapshotType" );
// Determine the snapshot type based on the entered snapshot type string.
// See if the snapshot type was specified, if not, return all context
if ( pwszType == NULL || pwszType[0] == L'\0' )
{
return VSS_CTX_ALL;
}
INT idx;
// Determine type of snapshot
for ( idx = 0; g_asAdmTypeNames[idx].pwszName != NULL; ++idx )
{
if ( ( dCurrentSKU & g_asAdmTypeNames[idx].dwSKUs ) &&
( ::_wcsicmp( pwszType, g_asAdmTypeNames[idx].pwszName ) == 0 ) )
{
break;
}
}
if ( g_asAdmTypeNames[idx].pwszName == NULL )
{
ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_INVALID_OPTION_VALUE,
L"DetermineSnapshotType: Invalid type specified: %s",
pwszType );
}
//
// Now return the context
//
return( g_asAdmTypeNames[idx].lSnapshotContext );
}
LPWSTR CVssAdminCLI::DetermineSnapshotType(
IN LONG lSnapshotAttributes
) throw(HRESULT)
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DetermineSnapshotType" );
// Determine the snapshot type string based on the snapshot attributes
LPWSTR pwszType = NULL;
INT idx;
// Determine type of snapshot
for ( idx = 0; g_asAdmTypeNames[idx].pwszName != NULL; ++idx )
{
if ( g_asAdmTypeNames[idx].lSnapshotContext == ( lSnapshotAttributes & VSS_CTX_ATTRIB_MASK ) )
break;
}
if ( g_asAdmTypeNames[idx].pwszName == NULL )
{
ft.Trace( VSSDBG_VSSADMIN, L"DetermineSnapshotType: Invalid context in lSnapshotAttributes: 0x%08x",
lSnapshotAttributes );
LPWSTR pwszMsg = GetMsg( FALSE, MSG_UNKNOWN );
if ( pwszMsg == NULL )
{
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED,
L"Error on loading the message string id %d. 0x%08lx",
MSG_UNKNOWN, ::GetLastError() );
}
return pwszMsg;
}
//
// Now return the context
//
::VssSafeDuplicateStr( ft, pwszType, g_asAdmTypeNames[idx].pwszName );
return pwszType;
}