// Query the properties of the given shadow copy
void VssClient::GetSnapshotProperties(VSS_ID snapshotID)
{
    FunctionTracer ft(DBG_INFO);

    // Get the shadow copy properties
    VSS_SNAPSHOT_PROP Snap;
    CHECK_COM(m_pVssObject->GetSnapshotProperties(snapshotID, &Snap));

    // Automatically call VssFreeSnapshotProperties on this structure at the end of scope
    CAutoSnapPointer snapAutoCleanup(&Snap);

    // Print the properties of this shadow copy 
    PrintSnapshotProperties(Snap);
}
// Query all the shadow copies in the given set
// If snapshotSetID is NULL, just query all shadow copies in the system
void VssClient::QuerySnapshotSet(VSS_ID snapshotSetID)
{
    FunctionTracer ft(DBG_INFO);

    if (snapshotSetID == GUID_NULL)
        ft.WriteLine(L"\nQuerying all shadow copies in the system ...\n");
    else
        ft.WriteLine(L"\nQuerying all shadow copies with the SnapshotSetID " WSTR_GUID_FMT L" ...\n", GUID_PRINTF_ARG(snapshotSetID));
    
    // Get list all shadow copies. 
    CComPtr<IVssEnumObject> pIEnumSnapshots;
    HRESULT hr = m_pVssObject->Query( GUID_NULL, 
            VSS_OBJECT_NONE, 
            VSS_OBJECT_SNAPSHOT, 
            &pIEnumSnapshots );

    CHECK_COM_ERROR(hr, L"m_pVssObject->Query(GUID_NULL, VSS_OBJECT_NONE, VSS_OBJECT_SNAPSHOT, &pIEnumSnapshots )")

    // If there are no shadow copies, just return
    if (hr == S_FALSE) {
        if (snapshotSetID == GUID_NULL)
            ft.WriteLine(L"\nThere are no shadow copies in the system\n");
        return;
    } 

    // Enumerate all shadow copies. 
    VSS_OBJECT_PROP Prop;
    VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
    
    while(true)
    {
        // Get the next element
        ULONG ulFetched;
        hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
        CHECK_COM_ERROR(hr, L"pIEnumSnapshots->Next( 1, &Prop, &ulFetched )")

        // We reached the end of list
        if (ulFetched == 0)
            break;

        // Automatically call VssFreeSnapshotProperties on this structure at the end of scope
        CAutoSnapPointer snapAutoCleanup(&Snap);

        // Print the shadow copy (if not filtered out)
        if ((snapshotSetID == GUID_NULL) || (Snap.m_SnapshotSetId == snapshotSetID))
            PrintSnapshotProperties(Snap);
    }
}
// Return the list of snapshot volume devices in this snapshot set
vector<wstring> VssClient::GetSnapshotDevices(VSS_ID snapshotSetID)
{
    FunctionTracer ft(DBG_INFO);

    vector<wstring> volumes;
        
    // Get list all snapshots. 
    CComPtr<IVssEnumObject> pIEnumSnapshots;
    CHECK_COM( m_pVssObject->Query( GUID_NULL, VSS_OBJECT_NONE, VSS_OBJECT_SNAPSHOT, &pIEnumSnapshots ) );

    // Enumerate all snapshots. 
    VSS_OBJECT_PROP Prop;
    VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
    while(true)
    {
        // Get the next element
        ULONG ulFetched = 0;
        CHECK_COM(pIEnumSnapshots->Next( 1, &Prop, &ulFetched ));

        // We reached the end of list
        if (ulFetched == 0)
            break;

        // Automatically call VssFreeSnapshotProperties on this structure at the end of scope
        CAutoSnapPointer snapAutoCleanup(&Snap);

        // Ignore snapshots not part of this set
        if (Snap.m_SnapshotSetId == snapshotSetID)
        {
            // Get the snapshot device object name which is a volume guid name for persistent snapshot
            // and a device name for non persistent snapshot.
            // The volume guid name and the device name we obtained here might change after breaksnapshot
            // depending on if the disk signature is reverted, but those cached names should still work
            // as symbolic links, in which case they can not persist after reboot.
            wstring snapshotDeviceObjectName = Snap.m_pwszSnapshotDeviceObject;

            // Add it to the array
            ft.WriteLine(L"- Will convert %s to read-write ...", snapshotDeviceObjectName.c_str());
            volumes.push_back(snapshotDeviceObjectName);
        }
    }

    // Return the list of snapshot volumes
    return volumes;
}
void VssClient::RevertToSnapshot(VSS_ID snapshotID)
{
    FunctionTracer ft(DBG_INFO);

    // Get the shadow copy properties
    VSS_SNAPSHOT_PROP Snap;
    CHECK_COM(m_pVssObject->GetSnapshotProperties(snapshotID, &Snap));
    
    // Automatically call VssFreeSnapshotProperties on this structure at the end of scope
    CAutoSnapPointer snapAutoCleanup(&Snap);

    ft.WriteLine(L"- Reverting to shadow copy " WSTR_GUID_FMT L" on %s from provider " WSTR_GUID_FMT L" [0x%08lx]...", 
            GUID_PRINTF_ARG(Snap.m_SnapshotId),
            Snap.m_pwszOriginalVolumeName,
            GUID_PRINTF_ARG(Snap.m_ProviderId),
            Snap.m_lSnapshotAttributes);
    
    bool bBlock = false;
    CHECK_COM(::ShouldBlockRevert(Snap.m_pwszOriginalVolumeName, &bBlock));
    if (bBlock)
    {
        ft.WriteLine(L"Revert is disabled on the volume %s because of writers",
                Snap.m_pwszOriginalVolumeName);
        return;
    }

    HRESULT hr = m_pVssObject->RevertToSnapshot(snapshotID, true);
    if (FAILED(hr))
    {
        switch (hr)
        {
        case VSS_E_OBJECT_NOT_FOUND:
                ft.WriteLine(L"Shadow Copy with id " WSTR_GUID_FMT L" was not found",
                    GUID_PRINTF_ARG(snapshotID));
                return;
            case VSS_E_VOLUME_IN_USE:
                ft.WriteLine(L"The voulume %s cannot be reverted since it is in use",
                    Snap.m_pwszOriginalVolumeName);
                return;
            case VSS_E_REVERT_IN_PROGRESS:
                ft.WriteLine(L"A revert is current in progress on the volume %s",
                    Snap.m_pwszOriginalVolumeName);
                return;
            case VSS_E_VOLUME_NOT_SUPPORTED:
                ft.WriteLine(L"Revert is not supported on the volume %s",
                    Snap.m_pwszOriginalVolumeName);
                return;            
            default:
                ft.WriteLine(L"RevertToSnapshot on Shadow Copy " WSTR_GUID_FMT L" failed with error 0x%08lx",
                            GUID_PRINTF_ARG(snapshotID),
                            hr);
                return;
        }
    }

    CComPtr<IVssAsync> pAsync;
    hr = m_pVssObject->QueryRevertStatus(Snap.m_pwszOriginalVolumeName, &pAsync);
    if (hr != VSS_E_OBJECT_NOT_FOUND)
    {
        if (FAILED(hr))
        {
            ft.WriteLine(L"QueryRevertStatus failed with error 0x%08lx", hr);
            ft.WriteLine(L"Revert may still be in progress, but cannot be tracked");
            return;
        }

        hr = pAsync->Wait();
        if (FAILED(hr))
        {
            ft.WriteLine(L"IVssAsync::Wait failed with error 0x%08lx", hr);
            ft.WriteLine(L"Revert may still be in progress, but cannot be tracked");
            return;
        }
    }

    ft.WriteLine(L"The shadow copy has been successfully reverted");
}
Exemple #5
0
// Delete all the shadow copies in the system
void VssClient::DeleteAllSnapshots()
{
    FunctionTracer ft(DBG_INFO);

    // Get list all shadow copies. 
    CComPtr<IVssEnumObject> pIEnumSnapshots;
    HRESULT hr = m_pVssObject->Query( GUID_NULL, 
            VSS_OBJECT_NONE, 
            VSS_OBJECT_SNAPSHOT, 
            &pIEnumSnapshots );

    CHECK_COM_ERROR(hr, L"m_pVssObject->Query(GUID_NULL, VSS_OBJECT_NONE, VSS_OBJECT_SNAPSHOT, &pIEnumSnapshots )")

    // If there are no shadow copies, just return
    if (hr == S_FALSE) 
    {
        ft.WriteLine(L"\nThere are no shadow copies on the system\n");
        return;
    } 

    // Enumerate all shadow copies. Delete each one
    VSS_OBJECT_PROP Prop;
    VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
    
    while(true)
    {
        // Get the next element
        ULONG ulFetched;
        hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
        CHECK_COM_ERROR(hr, L"pIEnumSnapshots->Next( 1, &Prop, &ulFetched )")

        // We reached the end of list
        if (ulFetched == 0)
            break;

        // Automatically call VssFreeSnapshotProperties on this structure at the end of scope
        CAutoSnapPointer snapAutoCleanup(&Snap);

        // Print the deleted shadow copy...
        ft.WriteLine(L"- Deleting shadow copy " WSTR_GUID_FMT L" on %s from provider " WSTR_GUID_FMT L" [0x%08lx]...", 
            GUID_PRINTF_ARG(Snap.m_SnapshotId),
            Snap.m_pwszOriginalVolumeName,
            GUID_PRINTF_ARG(Snap.m_ProviderId),
            Snap.m_lSnapshotAttributes);

        // Perform the actual deletion
        LONG lSnapshots = 0;
        VSS_ID idNonDeletedSnapshotID = GUID_NULL;
        hr = m_pVssObject->DeleteSnapshots(
            Snap.m_SnapshotId, 
            VSS_OBJECT_SNAPSHOT,
            FALSE,
            &lSnapshots,
            &idNonDeletedSnapshotID);

        if (FAILED(hr))
        {
            ft.WriteLine(L"Error while deleting shadow copies...");
            ft.WriteLine(L"- Last shadow copy that could not be deleted: " WSTR_GUID_FMT, GUID_PRINTF_ARG(idNonDeletedSnapshotID));
            CHECK_COM_ERROR(hr, L"m_pVssObject->DeleteSnapshots(Snap.m_SnapshotId, VSS_OBJECT_SNAPSHOT,FALSE,&lSnapshots,&idNonDeleted)");
        }
    }
}