// Discover excluded components that have file groups outside the shadow set.
void GoogleVssClient::DiscoverNonShadowedExcludedComponents(
    const vector<wstring>& volume_names) {
  // Discover components that should be excluded from the shadow set having
  // at least one File Descriptor requiring volumes not in the shadow set.
  LogDebugMessage(
      L"Discover components that reside outside the shadow set ...");
  for (unsigned idx = 0; idx < writers_.size(); idx++) {
    VssWriter* writer = &writers_[idx];
    if (writer->isExcluded) {
      continue;
    }

    for (unsigned icx = 0; icx < writer->components.size(); icx++) {
      VssComponent* component = &(writer->components[icx]);
      if (component->isExcluded) {
        continue;
      }

      for (unsigned vol = 0; vol < component->affected_volumes.size(); vol++) {
        if (!FindStringInList(component->affected_volumes[vol], volume_names)) {
          wstring volume_path;
          GetDisplayNameForVolume(component->affected_volumes[vol],
                                  &volume_path);
          LogDebugMessage(
              L"- Component '%s' from writer '%s' is excluded from backup "
              L"(it requires volume %s [%s] in the shadow set)",
              component->fullPath.c_str(), writer->name.c_str(),
              component->affected_volumes[vol].c_str(), volume_path.c_str());
          component->isExcluded = true;
          break;
        }
      }
    }
  }
}
Example #2
0
// Initialize from a IVssWMComponent
void VssComponent::Initialize(wstring writerNameParam, IVssWMComponent * pComponent)
{
    FunctionTracer ft(DBG_INFO);

    writerName = writerNameParam;

    // Get the component info
    PVSSCOMPONENTINFO pInfo = NULL;
    CHECK_COM(pComponent->GetComponentInfo (&pInfo));

    // Initialize local members
    name = BSTR2WString(pInfo->bstrComponentName);
    logicalPath = BSTR2WString(pInfo->bstrLogicalPath);
    caption = BSTR2WString(pInfo->bstrCaption);
    type = pInfo->type;
    isSelectable = pInfo->bSelectable;
    notifyOnBackupComplete = pInfo->bNotifyOnBackupComplete;

    // Compute the full path
    fullPath = AppendBackslash(logicalPath) + name;
    if (fullPath[0] != L'\\')
        fullPath = wstring(L"\\") + fullPath;

    // Get file list descriptors
    for(unsigned i = 0; i < pInfo->cFileCount; i++)
    {
        CComPtr<IVssWMFiledesc> pFileDesc;
        CHECK_COM(pComponent->GetFile (i, &pFileDesc));

        VssFileDescriptor desc;
        desc.Initialize(pFileDesc, VSS_FDT_FILELIST);
        descriptors.push_back(desc);
    }
    
    // Get database descriptors
    for(unsigned i = 0; i < pInfo->cDatabases; i++)
    {
        CComPtr<IVssWMFiledesc> pFileDesc;
        CHECK_COM(pComponent->GetDatabaseFile (i, &pFileDesc));

        VssFileDescriptor desc;
        desc.Initialize(pFileDesc, VSS_FDT_DATABASE);
        descriptors.push_back(desc);
    }
    
    // Get log descriptors
    for(unsigned i = 0; i < pInfo->cLogFiles; i++)
    {
        CComPtr<IVssWMFiledesc> pFileDesc;
        CHECK_COM(pComponent->GetDatabaseLogFile (i, &pFileDesc));

        VssFileDescriptor desc;
        desc.Initialize(pFileDesc, VSS_FDT_DATABASE_LOG);
        descriptors.push_back(desc);
    }
    

#ifdef VSS_SERVER
    // Get dependencies
    for(unsigned i = 0; i < pInfo->cDependencies; i++)
    {
        CComPtr<IVssWMDependency> pDependency;
        CHECK_COM(pComponent->GetDependency(i, &pDependency));

        VssDependency dependency;
        dependency.Initialize(pDependency);
        dependencies.push_back(dependency);
    }
#endif


    pComponent->FreeComponentInfo (pInfo);

    // Compute the affected paths and volumes
    for(unsigned i = 0; i < descriptors.size(); i++)
    {
        if (!FindStringInList(descriptors[i].expandedPath, affectedPaths))
            affectedPaths.push_back(descriptors[i].expandedPath);

        if (!FindStringInList(descriptors[i].affectedVolume, affectedVolumes))
            affectedVolumes.push_back(descriptors[i].affectedVolume);
    }


    sort( affectedPaths.begin( ), affectedPaths.end( ) );
}
Example #3
0
// Make the volumes in this list read-write using VDS API
void VssClient::MakeVolumesReadWrite(vector<wstring> snapshotVolumes)
{
    FunctionTracer ft(DBG_INFO);

    ft.Trace(DBG_INFO, L"Clearing read-only on %d volumes ... ", snapshotVolumes.size());

    // Get the VDS loader
    CComPtr<IVdsServiceLoader> pLoader;
    CHECK_COM(CoCreateInstance(CLSID_VdsLoader,
        NULL,
        CLSCTX_LOCAL_SERVER,
        __uuidof(IVdsServiceLoader),
        (void **)&pLoader));

    // Get the service interface pointer
    CComPtr<IVdsService> pService;
    CHECK_COM(pLoader->LoadService(NULL, &pService));

    CHECK_COM(pService->WaitForServiceReady());

    vector<wstring> clearedVolumes;

    // Get the unique volume names for the cached snapshot volume names 
    // which might change after the break
    vector<wstring> snapshotVolumeUniqueNames;
    for (unsigned i = 0; i < snapshotVolumes.size( ); i++)
        snapshotVolumeUniqueNames.push_back(GetUniqueVolumeNameForMountPoint(snapshotVolumes[i]));


    // Enumerate the Software providers
    HRESULT hr;
    CComPtr<IEnumVdsObject> pEnumProvider;
    CHECK_COM(pService->QueryProviders(VDS_QUERY_SOFTWARE_PROVIDERS,&pEnumProvider));
    vector< CComPtr<IUnknown> > providers = EnumerateVdsObjects(pEnumProvider);
    for(unsigned iProvider = 0; iProvider < providers.size(); iProvider++)
    {
        // QueryInterface for IVdsSwProvider
        CComQIPtr<IVdsSwProvider> pSwProvider = providers[iProvider];

        ft.Trace(DBG_INFO, L"- Provider %d", iProvider);

        // Enumerate packs for this provider
        CComPtr<IEnumVdsObject> pEnumPack;
        CHECK_COM(pSwProvider->QueryPacks(&pEnumPack));
        vector< CComPtr<IUnknown> > packs = EnumerateVdsObjects(pEnumPack);
        for(unsigned iPack = 0; iPack < packs.size(); iPack++)
        {
            // QueryInterface for IVdsPack
            CComQIPtr<IVdsPack> pPack = packs[iPack];

            ft.Trace(DBG_INFO, L"- Pack %d/%d", iPack, iProvider);

            // Enumerate volumes
            CComPtr<IEnumVdsObject> pEnumVolumes;
            hr = pPack->QueryVolumes(&pEnumVolumes);
            if (FAILED(hr)) {
                if (hr == VDS_E_INVALID_PACK) {
                    hr = S_OK;
                } else ft.Trace( DBG_INFO, L"COM Error: GetProperties for VDS pack failed. hr = 0x%08lx", hr);
                continue;
            }

            vector< CComPtr<IUnknown> > volumes = EnumerateVdsObjects(pEnumVolumes);
            for(unsigned iVol = 0; iVol < volumes.size(); iVol++)
            {
                // QueryInterface for IVdsVolumeMF and IVdsVolume
                CComQIPtr<IVdsVolume> pVolume = volumes[iVol];

                // Get volume properties. Ignore deleted volumes
                VDS_VOLUME_PROP volProp;
                HRESULT innerHR = pVolume->GetProperties(&volProp);
                if (innerHR == VDS_E_OBJECT_DELETED )
                    continue;

                CHECK_COM_ERROR(innerHR, L"pVolume->GetProperties(&volProp)");

                // Skip failed volumes
                if ( (volProp.status == VDS_VS_FAILED) && (volProp.health == VDS_H_FAILED) || !volProp.pwszName)
                    continue;

                // Skip hidden volumes (it fails GetVolumeNameForMountPoint)
                if (volProp.ulFlags & VDS_VF_HIDDEN)
                    continue;

                // Automatically call CoTaskMemFree on this pointer at the end of scope
                CAutoComPointer ptrAutoCleanup(volProp.pwszName);

                // Get the initial device name (normally with the format \\?\GLOBALROOT\Device\HarddiskVolumeXX)
                wstring name = volProp.pwszName;

                // Get the unique volume guid name for this device name.
                wstring uniqueVolumeName = GetUniqueVolumeNameForMountPoint(name);

                ft.Trace(DBG_INFO, L"- Found volume %s [device = %s] in %d/%d", 
                    uniqueVolumeName.c_str(), name.c_str(), iPack, iProvider);

                // Check to see if this is one of our volumes. If not, continue
                if (!FindStringInList(uniqueVolumeName, snapshotVolumeUniqueNames))
                    continue;

                // Clear the read-only flag
                ft.WriteLine(L"- Clearing read-only flag for volume %s [%s] ...", uniqueVolumeName.c_str(), name.c_str());

                CHECK_COM(pVolume->ClearFlags(VDS_VF_READONLY));

                // Force-dismounts the volume 
                // since we want to re-mount the file system as read-write
                CComQIPtr<IVdsVolumeMF> pVolumeMF = pVolume;
                ft.WriteLine(L"- Dismounting volume %s ...", name.c_str());
                CHECK_COM(pVolumeMF->Dismount(TRUE, FALSE));

                clearedVolumes.push_back(uniqueVolumeName);
            }
        }
    }

    // Check that all volumes have been cleared ...
    if (clearedVolumes.size() != snapshotVolumeUniqueNames.size())
    {
        ft.WriteLine(L"WARNING: some volumes were not succesfully converted to read-write!");

        for (unsigned i = 0; i < snapshotVolumeUniqueNames.size(); i++)
            if (!FindStringInList(snapshotVolumeUniqueNames[i], clearedVolumes))
                ft.WriteLine(L"- Volume %s not found on the system. Clearing the read-only flag failed on it.",
                    snapshotVolumeUniqueNames[i].c_str());
    }
}