Reputation: 567
Hi I am having trouble getting the volume shadow copy service to work for my program written in C++ with QT. The snapshot is created successfully however I cannot access it either through my program or through the Windows run prompt (not sure if that's even possible in the first place). I have tried accessing the snapshot using both \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy27\ and \Device\HarddiskVolumeShadowCopy28\ as prefixes (as generated from my program with the right number on the end). Also the snapshots look like they are differential snapshots even though I used VSS_BT_COPY and VSS_BT_FULL as the state. I had been trying VSS_CTX_NAS_ROLLBACK as the context which created persistent snapshots so I tried deleting them all before attempting to access the snapshots in the program once again but this time with context VSS_CTX_FILE_SHARE_BACKUP, without success. Here's the snapshot creation code (error handling removed):
void Worker::setupVSS(BackupJob &job)
{
HRESULT result;
//backupComponents is a class member variable
//IVssBackupComponents *backupComponents;
result = CreateVssBackupComponents(&backupComponents);
VSS_ID snapshotSetId;
result = backupComponents->InitializeForBackup();
//tried both of these
//result = backupComponents->SetBackupState(FALSE, FALSE, VSS_BT_COPY);
result = backupComponents->SetBackupState(FALSE, FALSE, VSS_BT_FULL);
//tried both of these
//result = backupComponents->SetContext(VSS_CTX_NAS_ROLLBACK);
result = backupComponents->SetContext(VSS_CTX_FILE_SHARE_BACKUP);
result = backupComponents->StartSnapshotSet(&snapshotSetId);
VSS_ID snapshotId;
wchar_t *source;
//this line gets the drive letter with : and \
QString driveLetter = job.getSource().mid(0,3);
driveLetter.toWCharArray(source);
//QString("D:\\").toWCharArray(source);
result = backupComponents->AddToSnapshotSet(source, GUID_NULL, &snapshotId);
IVssAsync *async;
result = backupComponents->DoSnapshotSet(&async);
result = async->Wait();
async->Release();
VSS_SNAPSHOT_PROP prop;
result = backupComponents->GetSnapshotProperties(snapshotId, &prop);
QString vssPrefix = QString::fromWCharArray(prop.m_pwszSnapshotDeviceObject);
job.setVSSPrefix(vssPrefix);
}
And here's the file open code:
QString sourceFileString = job.getCurrentFileSource(fileCount);
if (job.getVSS())
{
QString prefix = job.getVSSPrefix();
//tried this comment to remove ? and globalroot from prefix without success
//prefix = prefix.mid(prefix.indexOf("\\Device"));
prefix.append("\\");
prefix = QDir::fromNativeSeparators(prefix);
sourceFileString.replace(0,3,prefix);
}
QFile sourceFile(sourceFileString);
if (!sourceFile.open(QIODevice::ReadOnly))
{
updateStatus("<font color=\"red\">ERROR: Couldn't open source file " + QDir::toNativeSeparators(sourceFile.fileName()) + ".</font>");
updateStatus("<font color=\"red\">ERROR: " + sourceFile.errorString() + "</font>");
errorsFound = true;
break;
}
Here are the errors QT gives me from the failed file open attempt:
01-13-2017 01:42 PM ERROR: Couldn't open source file \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy38\Users\Josh\Desktop\awef\awef3\awefawefawef - Copy (10)waefawefawefawefawefawef - Copyawefawefawefawefawefwefawefawef.docx.
01-13-2017 01:42 PM ERROR: The network path was not found.
01-13-2017 01:44 PM ERROR: Couldn't open source file \Device\HarddiskVolumeShadowCopy40\Users\Josh\Desktop\awef\awef3\awefawefawef - Copy (10)waefawefawefawefawefawef - Copyawefawefawefawefawefwefawefawef.docx.
01-13-2017 01:44 PM ERROR: The system cannot find the path specified.
When I try to open the same files from the run prompt it just says Windows cannot find filename etc..
I verified the snapshots are created using vssadmin list shadows with this output:
Contents of shadow copy set ID: {968d9034-3aee-494b-ae78-82af04a15686} Contained 1 shadow copies at creation time: 1/13/2017 1:40:09 PM Shadow Copy ID: {1109bad9-7d01-40f2-9141-cda25b313810} Original Volume: (C:)\?\Volume{b3fc9fb7-0000-0000-0000-100000000000}\ Shadow Copy Volume: \?\GLOBALROOT\Device\HarddiskVolumeShadowCopy38 Originating Machine: joshdesktop10 Service Machine: joshdesktop10 Provider: 'Microsoft Software Shadow Copy provider 1.0' Type: FileShareRollback Attributes: No writers, Differential
Contents of shadow copy set ID: {d6519b09-8325-4c1c-90bc-935a39f2189a} Contained 1 shadow copies at creation time: 1/13/2017 1:44:07 PM Shadow Copy ID: {21e1b83e-db79-4a29-95b0-65cc5c7d08a8} Original Volume: (C:)\?\Volume{b3fc9fb7-0000-0000-0000-100000000000}\ Shadow Copy Volume: \?\GLOBALROOT\Device\HarddiskVolumeShadowCopy40 Originating Machine: joshdesktop10 Service Machine: joshdesktop10 Provider: 'Microsoft Software Shadow Copy provider 1.0' Type: FileShareRollback Attributes: No writers, Differential
As you can see they are differential backups ... could this be the problem?
Any ideas?? Thanks!
Upvotes: 0
Views: 936
Reputation: 567
Google has enlightened me... as here you cannot access VSS snapshot volumes without using the Win32 API functions FindFirstFile/FindNextFile. There is a workaround ... mount the snapshot volume as a symbolic link and use the link to access the files. Here's the code I used:
VSS_SNAPSHOT_PROP prop;
result = backupComponents->GetSnapshotProperties(snapshotId, &prop);
wchar_t *snapVol = prop.m_pwszSnapshotDeviceObject;
wcsncat(snapVol, L"\\", 1);
if (QDir("C:\\repVSSVol").exists())
RemoveDirectory(L"C:\\repVSSVol");
if (CreateSymbolicLink(L"C:\\repVSSVol", snapVol, SYMBOLIC_LINK_FLAG_DIRECTORY) == 0)
win32Error(TEXT("CreateSymbolicLink"));
Also be careful removing symbolic directory links as explained here.
Upvotes: 0