예제 #1
0
void VssClient::BreakSnapshotSetEx(VSS_ID snapshotSetID, DWORD dwBreakExFlags)
{
    FunctionTracer ft(DBG_INFO);

    ft.WriteLine(L"- Calling BreakSnapshotSetEx on " WSTR_GUID_FMT L" ...", GUID_PRINTF_ARG(snapshotSetID));

    if (!(dwBreakExFlags & VSS_BREAKEX_FLAG_MASK_LUNS)                &&
        !(dwBreakExFlags & VSS_BREAKEX_FLAG_MAKE_READ_WRITE)          &&
        !(dwBreakExFlags & VSS_BREAKEX_FLAG_REVERT_IDENTITY_ALL)    &&
        !(dwBreakExFlags & VSS_BREAKEX_FLAG_REVERT_IDENTITY_NONE))
        ft.WriteLine(L"- No BreakSnapshotSetEx flags, can use -mask, -rw, -forcerevert, or -norevert");


    CComPtr<IVssBackupComponentsEx2> pVssObjectEx;
    CHECK_COM(m_pVssObject->QueryInterface(__uuidof(IVssBackupComponentsEx2), (void**)&pVssObjectEx));

    CComPtr<IVssAsync>  pAsync;

    CHECK_COM(pVssObjectEx->BreakSnapshotSetEx(snapshotSetID, dwBreakExFlags, &pAsync));

    // Waits for the async operation to finish and checks the result
    WaitAndCheckForAsyncOperation(pAsync);

    ft.WriteLine(L"BreakEx done.");

}
예제 #2
0
// Lists the status for all writers
void VssClient::ListWriterStatus()
{
    FunctionTracer ft(DBG_INFO);

    ft.WriteLine(L"Listing writer status ..."); 
    
    // Gets the number of writers in the gathered status info
    // (WARNING: GatherWriterStatus must be called before)
    unsigned cWriters = 0;
    CHECK_COM(m_pVssObject->GetWriterStatusCount(&cWriters));
    ft.WriteLine(L"- Number of writers that responded: %u", cWriters);  

    // Enumerate each writer
    for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
    {
        VSS_ID idInstance = GUID_NULL;
        VSS_ID idWriter= GUID_NULL;
        VSS_WRITER_STATE eWriterStatus = VSS_WS_UNKNOWN;
        CComBSTR bstrWriterName;
        HRESULT hrWriterFailure = S_OK;

        // Get writer status
        CHECK_COM(m_pVssObject->GetWriterStatus(iWriter,
                             &idInstance,
                             &idWriter,
                             &bstrWriterName,
                             &eWriterStatus,
                             &hrWriterFailure));

        // Print writer status
        ft.WriteLine(L"\n"
            L"* WRITER \"%s\"\n"
            L"   - Status: %d (%s)\n" 
            L"   - Writer Failure code: 0x%08lx (%s)\n" 
            L"   - Writer ID: " WSTR_GUID_FMT L"\n"
            L"   - Instance ID: " WSTR_GUID_FMT L"\n",
            (PWCHAR)bstrWriterName,
            eWriterStatus, GetStringFromWriterStatus(eWriterStatus).c_str(), 
            hrWriterFailure, FunctionTracer::HResult2String(hrWriterFailure).c_str(),
            GUID_PRINTF_ARG(idWriter),
            GUID_PRINTF_ARG(idInstance)
            );
    }
}
예제 #3
0
//
// Break the given shadow copy set to read or read-write
//
// Setting the parameter pVolumeNames makes this function return immediately after VSS breaks the
// shadow copy set. This is useful in the fast recover scenario: if the LUN after break is in an
// offline mode, the requster must wait for the LUN online in order to call VDS to make it read-write.
void VssClient::BreakSnapshotSet(VSS_ID snapshotSetID, bool makeReadWrite, vector<wstring> *pVolumeNames)
{
    FunctionTracer ft(DBG_INFO);

    if (makeReadWrite)
    {
        // If we want read-write treatment, compute a list of volumes in the shadow copy set
        vector<wstring> snapshotDeviceList;
        snapshotDeviceList = GetSnapshotDevices(snapshotSetID);

        ft.WriteLine(L"- Calling BreakSnapshotSet on " WSTR_GUID_FMT L" ...", GUID_PRINTF_ARG(snapshotSetID));

        // Break the shadow copy set
        CHECK_COM(m_pVssObject->BreakSnapshotSet(snapshotSetID));

        // If we want to delay read-write treatment, fill out the volume name list and return
        if (pVolumeNames)
        {
            *pVolumeNames = snapshotDeviceList;
            return;
        }

        ft.WriteLine(L"- Making shadow copy devices from " WSTR_GUID_FMT L" read-write...", GUID_PRINTF_ARG(snapshotSetID));

        // Make the snapshot devices read-write
        MakeVolumesReadWrite(snapshotDeviceList);
    }
    else
    {
        ft.WriteLine(L"- Calling BreakSnapshotSet on " WSTR_GUID_FMT L" ...", GUID_PRINTF_ARG(snapshotSetID));

        // Just break the snapshot set
        CHECK_COM(m_pVssObject->BreakSnapshotSet(snapshotSetID));

        ft.WriteLine(L"Break done.");
    }
}
예제 #4
0
// Delete the given shadow copy set 
void VssClient::DeleteSnapshotSet(VSS_ID snapshotSetID)
{
    FunctionTracer ft(DBG_INFO);

    // Print the deleted shadow copy...
    ft.WriteLine(L"- Deleting shadow copy set " WSTR_GUID_FMT L" ...", GUID_PRINTF_ARG(snapshotSetID));

    // Perform the actual deletion
    LONG lSnapshots = 0;
    VSS_ID idNonDeletedSnapshotID = GUID_NULL;
    HRESULT hr = m_pVssObject->DeleteSnapshots(
        snapshotSetID, 
        VSS_OBJECT_SNAPSHOT_SET,
        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(snapshotSetID, VSS_OBJECT_SNAPSHOT_SET,FALSE,&lSnapshots,&idNonDeleted)");
    }
}
예제 #5
0
// Print the properties for the given snasphot
void VssClient::PrintSnapshotProperties(VSS_SNAPSHOT_PROP & prop)
{
    FunctionTracer ft(DBG_INFO);
    
    LONG lAttributes = prop.m_lSnapshotAttributes;

    ft.WriteLine(L"* SNAPSHOT ID = " WSTR_GUID_FMT L" ...", GUID_PRINTF_ARG(prop.m_SnapshotId));
    ft.WriteLine(L"   - Shadow copy Set: " WSTR_GUID_FMT, GUID_PRINTF_ARG(prop.m_SnapshotSetId));
    ft.WriteLine(L"   - Original count of shadow copies = %d", prop.m_lSnapshotsCount);
    ft.WriteLine(L"   - Original Volume name: %s [%s]", 
        prop.m_pwszOriginalVolumeName, 
        GetDisplayNameForVolume(prop.m_pwszOriginalVolumeName).c_str()
        );
    ft.WriteLine(L"   - Creation Time: %s", VssTimeToString(prop.m_tsCreationTimestamp).c_str());
    ft.WriteLine(L"   - Shadow copy device name: %s", prop.m_pwszSnapshotDeviceObject);
    ft.WriteLine(L"   - Originating machine: %s", prop.m_pwszOriginatingMachine);
    ft.WriteLine(L"   - Service machine: %s", prop.m_pwszServiceMachine);

    if (prop.m_lSnapshotAttributes & VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY)
        ft.WriteLine(L"   - Exposed locally as: %s", prop.m_pwszExposedName);
    else if (prop.m_lSnapshotAttributes & VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY) 
    {
        ft.WriteLine(L"   - Exposed remotely as %s", prop.m_pwszExposedName);
        if (prop.m_pwszExposedPath && wcslen(prop.m_pwszExposedPath) > 0)
            ft.WriteLine(L"   - Path exposed: %s", prop.m_pwszExposedPath);
    }
    else
        ft.WriteLine(L"   - Not Exposed");

    ft.WriteLine(L"   - Provider id: " WSTR_GUID_FMT, GUID_PRINTF_ARG(prop.m_ProviderId));

    // Display the attributes
    wstring attributes;
    if (lAttributes & VSS_VOLSNAP_ATTR_TRANSPORTABLE)
        attributes  += wstring(L" Transportable");
    
    if (lAttributes & VSS_VOLSNAP_ATTR_NO_AUTO_RELEASE)
        attributes  += wstring(L" No_Auto_Release");
    else
        attributes  += wstring(L" Auto_Release");

    if (lAttributes & VSS_VOLSNAP_ATTR_PERSISTENT)
        attributes  += wstring(L" Persistent");

    if (lAttributes & VSS_VOLSNAP_ATTR_CLIENT_ACCESSIBLE)
        attributes  += wstring(L" Client_accessible");

    if (lAttributes & VSS_VOLSNAP_ATTR_HARDWARE_ASSISTED)
        attributes  += wstring(L" Hardware");

    if (lAttributes & VSS_VOLSNAP_ATTR_NO_WRITERS)
        attributes  += wstring(L" No_Writers");

    if (lAttributes & VSS_VOLSNAP_ATTR_IMPORTED)
        attributes  += wstring(L" Imported");

    if (lAttributes & VSS_VOLSNAP_ATTR_PLEX)
        attributes  += wstring(L" Plex");
    
    if (lAttributes & VSS_VOLSNAP_ATTR_DIFFERENTIAL)
        attributes  += wstring(L" Differential");

    ft.WriteLine(L"   - Attributes: %s", attributes.c_str());
    
    ft.WriteLine(L"");
}
예제 #6
0
// 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);
    }
}
예제 #7
0
// Check the status for all selected writers.
HRESULT GoogleVssClient::CheckSelectedWriterStatus() {
  // Gather writer status to detect potential errors.
  HRESULT hr = GatherWriterStatus();
  if (SUCCEEDED(hr)) {
    // Gets the number of writers in the gathered status info
    // (WARNING: GatherWriterStatus must be called before).
    unsigned writers = 0;
    hr = vss_object_->GetWriterStatusCount(&writers);
    if (FAILED(hr)) {
      LogDebugMessage(L"GetWriterStatusCount failed with error %x ", hr);
    } else {
      // Enumerate each writer.
      HRESULT hrWriterFailure = S_OK;
      for (unsigned writer = 0; writer < writers; writer++) {
        VSS_ID idInstance = GUID_NULL;
        VSS_ID idWriter = GUID_NULL;
        VSS_WRITER_STATE writerStatus = VSS_WS_UNKNOWN;
        CComBSTR bstrWriterName;
        // Get writer status.
        hr = vss_object_->GetWriterStatus(writer, &idInstance, &idWriter,
                                          &bstrWriterName, &writerStatus,
                                          &hrWriterFailure);
        // If the writer is not selected, just continue.
        if (!IsWriterSelected(idInstance)) {
          continue;
        }
        // If the writer is in non-stable state, break.
        switch (writerStatus) {
          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:
            // Print writer status.
            LogDebugMessage(
                L"ERROR: Selected writer '%s' is in failed state."
                L" Status: %d (%s), Writer Failure code: 0x%08lx,"
                L" Writer ID: " WSTR_GUID_FMT L" Instance ID: " WSTR_GUID_FMT,
                BstrToWString(bstrWriterName).c_str(), writerStatus,
                GetStringFromWriterStatus(writerStatus).c_str(),
                hrWriterFailure,
                GUID_PRINTF_ARG(idWriter), GUID_PRINTF_ARG(idInstance));
            // Stop here.
            hr = E_UNEXPECTED;
            break;
          default:
            break;
        }
        if (FAILED(hr)) {
          break;
        }
      }
    }
  }
  LogDebugMessage(L"CheckSelectedWriterStatus returned with %x", hr);
  return hr;
}
예제 #8
0
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");
}
예제 #9
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)");
        }
    }
}