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.
 
 
 
 
 
 

920 lines
27 KiB

#include "stdafx.hxx"
#include "vs_idl.hxx"
#include "vswriter.h"
#include "vsbackup.h"
#include <debug.h>
#include <cwriter.h>
#include <lmshare.h>
#include <lmaccess.h>
#include <time.h>
BOOL AssertPrivilege( LPCWSTR privName )
{
HANDLE tokenHandle;
BOOL stat = FALSE;
if ( OpenProcessToken (GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
&tokenHandle))
{
LUID value;
if ( LookupPrivilegeValue( NULL, privName, &value ) )
{
TOKEN_PRIVILEGES newState;
DWORD error;
newState.PrivilegeCount = 1;
newState.Privileges[0].Luid = value;
newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
/*
* We will always call GetLastError below, so clear
* any prior error values on this thread.
*/
SetLastError( ERROR_SUCCESS );
stat = AdjustTokenPrivileges (tokenHandle,
FALSE,
&newState,
(DWORD)0,
NULL,
NULL );
/*
* Supposedly, AdjustTokenPriveleges always returns TRUE
* (even when it fails). So, call GetLastError to be
* extra sure everything's cool.
*/
if ( (error = GetLastError()) != ERROR_SUCCESS )
{
stat = FALSE;
}
if ( !stat )
{
wprintf( L"AdjustTokenPrivileges for %s failed with %d",
privName,
error );
}
}
DWORD cbTokens;
GetTokenInformation (tokenHandle,
TokenPrivileges,
NULL,
0,
&cbTokens);
TOKEN_PRIVILEGES *pTokens = (TOKEN_PRIVILEGES *) new BYTE[cbTokens];
GetTokenInformation (tokenHandle,
TokenPrivileges,
pTokens,
cbTokens,
&cbTokens);
delete pTokens;
CloseHandle( tokenHandle );
}
return stat;
}
LPCWSTR GetStringFromUsageType (VSS_USAGE_TYPE eUsageType)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eUsageType)
{
case VSS_UT_BOOTABLESYSTEMSTATE: pwszRetString = L"BootableSystemState"; break;
case VSS_UT_SYSTEMSERVICE: pwszRetString = L"SystemService"; break;
case VSS_UT_USERDATA: pwszRetString = L"UserData"; break;
case VSS_UT_OTHER: pwszRetString = L"Other"; break;
default:
break;
}
return (pwszRetString);
}
LPCWSTR GetStringFromSourceType (VSS_SOURCE_TYPE eSourceType)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eSourceType)
{
case VSS_ST_TRANSACTEDDB: pwszRetString = L"TransactionDb"; break;
case VSS_ST_NONTRANSACTEDDB: pwszRetString = L"NonTransactionDb"; break;
case VSS_ST_OTHER: pwszRetString = L"Other"; break;
default:
break;
}
return (pwszRetString);
}
LPCWSTR GetStringFromRestoreMethod (VSS_RESTOREMETHOD_ENUM eRestoreMethod)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eRestoreMethod)
{
case VSS_RME_RESTORE_IF_NOT_THERE: pwszRetString = L"RestoreIfNotThere"; break;
case VSS_RME_RESTORE_IF_CAN_REPLACE: pwszRetString = L"RestoreIfCanReplace"; break;
case VSS_RME_STOP_RESTORE_START: pwszRetString = L"StopRestoreStart"; break;
case VSS_RME_RESTORE_TO_ALTERNATE_LOCATION: pwszRetString = L"RestoreToAlternateLocation"; break;
case VSS_RME_RESTORE_AT_REBOOT: pwszRetString = L"RestoreAtReboot"; break;
case VSS_RME_CUSTOM: pwszRetString = L"Custom"; break;
default:
break;
}
return (pwszRetString);
}
LPCWSTR GetStringFromWriterRestoreMethod (VSS_WRITERRESTORE_ENUM eWriterRestoreMethod)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eWriterRestoreMethod)
{
case VSS_WRE_NEVER: pwszRetString = L"RestoreNever"; break;
case VSS_WRE_IF_REPLACE_FAILS: pwszRetString = L"RestoreIfReplaceFailsI"; break;
case VSS_WRE_ALWAYS: pwszRetString = L"RestoreAlways"; break;
default:
break;
}
return (pwszRetString);
}
LPCWSTR GetStringFromComponentType (VSS_COMPONENT_TYPE eComponentType)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eComponentType)
{
case VSS_CT_DATABASE: pwszRetString = L"Database"; break;
case VSS_CT_FILEGROUP: pwszRetString = L"FileGroup"; break;
default:
break;
}
return (pwszRetString);
}
void PrintFiledesc(IVssWMFiledesc *pFiledesc, LPCWSTR wszDescription)
{
CComBSTR bstrPath;
CComBSTR bstrFilespec;
CComBSTR bstrAlternate;
CComBSTR bstrDestination;
bool bRecursive;
HRESULT hr;
CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
CHECK_SUCCESS(pFiledesc->GetFilespec(&bstrFilespec));
CHECK_NOFAIL(pFiledesc->GetRecursive(&bRecursive));
CHECK_NOFAIL(pFiledesc->GetAlternateLocation(&bstrAlternate));
CHECK_NOFAIL(pFiledesc->GetAlternateLocation(&bstrDestination));
wprintf (L"%s\n Path = %s, Filespec = %s, Recursive = %s\n",
wszDescription,
bstrPath,
bstrFilespec,
bRecursive ? L"yes" : L"no");
if (bstrAlternate && wcslen(bstrAlternate) > 0)
wprintf(L" Alternate Location = %s\n", bstrAlternate);
if (bstrDestination && wcslen(bstrDestination) > 0)
wprintf(L" Destination Location = %s\n", bstrDestination);
}
/*
void AddShares(IVssSnapshot **rgpSnapshot, UINT cSnapshot)
{
VSS_PWSZ wszDeviceName = NULL;
try
{
for(UINT iSnapshot = 0; iSnapshot < cSnapshot; iSnapshot++)
{
SHARE_INFO_502 info;
CHECK_SUCCESS(rgpSnapshot[iSnapshot]->GetDevice(&wszDeviceName));
WCHAR *wszPath = new WCHAR[wcslen(wszDeviceName) + 2];
if (wszPath != NULL)
{
wcscpy(wszPath, wszDeviceName);
wcscat(wszPath, L"\\");
memset(&info, 0, sizeof(info));
WCHAR wszName[20];
swprintf(wszName, L"Snapshot%d", iSnapshot);
info.shi502_netname = wszName;
info.shi502_type = STYPE_DISKTREE;
info.shi502_permissions = ACCESS_READ;
info.shi502_max_uses = 10;
info.shi502_path = wszDeviceName;
NET_API_STATUS status;
DWORD parm_err;
status = NetShareAdd(NULL, 502, (LPBYTE) &info, &parm_err);
}
CoTaskMemFree(wszDeviceName);
wszDeviceName = NULL;
}
}
catch(...)
{
}
if (wszDeviceName)
CoTaskMemFree(wszDeviceName);
}
*/
void DoAddToSnapshotSet
(
IN IVssBackupComponents *pvbc,
IN BSTR bstrPath,
IN LPWSTR wszVolumes,
OUT VSS_ID * rgpSnapshotId,
UINT *pcSnapshot
)
{
PWCHAR pwszPath = NULL;
PWCHAR pwszMountPointName = NULL;
WCHAR wszVolumeName [50];
ULONG ulPathLength;
ULONG ulMountpointBufferLength;
HRESULT hr;
ulPathLength = ExpandEnvironmentStringsW (bstrPath, NULL, 0);
pwszPath = (PWCHAR) malloc (ulPathLength * sizeof (WCHAR));
ulPathLength = ExpandEnvironmentStringsW (bstrPath, pwszPath, ulPathLength);
ulMountpointBufferLength = GetFullPathName (pwszPath, 0, NULL, NULL);
pwszMountPointName = (PWCHAR) malloc (ulMountpointBufferLength * sizeof (WCHAR));
bool fSuccess = false;
if (wcslen(pwszPath) >= 3 && pwszPath[1] == L':' && pwszPath[2] == L'\\')
{
wcsncpy(pwszMountPointName, pwszPath, 3);
pwszMountPointName[3] = L'\0';
fSuccess = true;
}
else
{
if (GetVolumePathNameW (pwszPath, pwszMountPointName, ulMountpointBufferLength))
fSuccess = true;
else
printf("GetVolumeMountPointW failed with error %d\npath=%s\n", GetLastError(), pwszPath);
}
if (fSuccess)
{
if (!GetVolumeNameForVolumeMountPointW (pwszMountPointName, wszVolumeName, sizeof (wszVolumeName) / sizeof (WCHAR)))
printf("GetVolumeNameForVolumeMountPointW failed with error %d", GetLastError());
else
{
if (NULL == wcsstr (wszVolumes, wszVolumeName))
{
if (L'\0' != wszVolumes [0])
wcscat (wszVolumes, L";");
wcscat (wszVolumes, wszVolumeName);
CHECK_SUCCESS
(
pvbc->AddToSnapshotSet
(
wszVolumeName,
GUID_NULL,
&rgpSnapshotId[*pcSnapshot]
)
);
*pcSnapshot += 1;
}
}
}
if (NULL != pwszPath) free (pwszPath);
if (NULL != pwszMountPointName) free (pwszMountPointName);
}
static LPCWSTR s_rgwszStates[] =
{
NULL,
L"STABLE",
L"WAIT_FOR_FREEZE",
L"WAIT_FOR_THAW",
L"WAIT_FOR_POST_SNAPSHOT",
L"WAIT_FOR_BACKUP_COMPLETE",
L"FAILED_AT_IDENTIFY",
L"FAILED_AT_PREPARE_BACKUP",
L"FAILED_AT_PREPARE_SNAPSHOT",
L"FAILED_AT_FREEZE",
L"FAILED_AT_THAW",
L"FAILED_AT_BACKUP_COMPLETE",
L"FAILED_AT_PRE_RESTORE",
L"FAILED_AT_POST_RESTORE"
};
void CheckStatus(IVssBackupComponents *pvbc, LPCWSTR wszWhen)
{
unsigned cWriters;
CComPtr<IVssAsync> pAsync;
HRESULT hr;
HRESULT hrResult;
CHECK_NOFAIL(pvbc->GatherWriterStatus(&pAsync));
CHECK_NOFAIL(pAsync->Wait());
CHECK_SUCCESS(pAsync->QueryStatus(&hrResult, NULL));
CHECK_NOFAIL(hrResult);
CHECK_NOFAIL(pvbc->GetWriterStatusCount(&cWriters));
wprintf(L"\n\nstatus %s (%d writers)\n\n", wszWhen, cWriters);
for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
{
VSS_ID idInstance;
VSS_ID idWriter;
VSS_WRITER_STATE status;
CComBSTR bstrWriter;
HRESULT hrWriterFailure;
CHECK_SUCCESS(pvbc->GetWriterStatus (iWriter,
&idInstance,
&idWriter,
&bstrWriter,
&status,
&hrWriterFailure));
wprintf (L"Status for writer %s: %s(0x%08lx%s%s)\n",
bstrWriter,
s_rgwszStates[status],
hrWriterFailure,
SUCCEEDED (hrWriterFailure) ? L"" : L" - ",
GetStringFromFailureType (hrWriterFailure));
}
pvbc->FreeWriterStatus();
}
// wait a maximum number of seconds before cancelling the operation
void LoopWait
(
IVssAsync *pAsync,
LONG seconds,
LPCWSTR wszOperation
)
{
clock_t start = clock();
HRESULT hr, hrStatus;
while(TRUE)
{
Sleep(1000);
CHECK_SUCCESS(pAsync->QueryStatus(&hrStatus, NULL));
if (hrStatus != VSS_S_ASYNC_PENDING)
break;
if (((clock() - start)/CLOCKS_PER_SEC) >= seconds)
break;
}
if (hrStatus == VSS_S_ASYNC_PENDING)
{
CHECK_NOFAIL(pAsync->Cancel());
wprintf(L"Called cancelled for %s.\n", wszOperation);
}
CHECK_SUCCESS(pAsync->QueryStatus(&hrStatus, NULL));
CHECK_NOFAIL(hrStatus);
}
extern "C" __cdecl wmain(int argc, WCHAR **argv)
{
WCHAR wszVolumes[2048];
wszVolumes[0] = L'\0';
UINT cSnapshot = 0;
VSS_ID rgpSnapshotId[64];
CTestVssWriter *pInstance = NULL;
bool bCreated = false;
bool bSubscribed = false;
HRESULT hr = S_OK;
bool bCoInitializeSucceeded = false;
try
{
HRESULT hr;
CComBSTR bstrXML;
CComBSTR bstrXMLOut;
LONG lWait = 0;
if (argc == 2 &&
wcslen(argv[1]) == 3 &&
argv[1][0] == L'-' &&
argv[1][1] == L'w' &&
(argv[1][2] >= L'0' && argv[1][2] <= L'9'||
argv[1][2] >= L'a' && argv[1][2] <= L'f'))
{
if (argv[1][2] >= L'0' && argv[1][2] <= L'9')
lWait = argv[1][2] - L'0';
else
lWait = argv[1][2] - L'a' + 10;
wprintf(L"wait parameter=%d.\n", lWait);
}
CHECK_SUCCESS(CoInitializeEx(NULL, COINIT_MULTITHREADED));
CComPtr<IGlobalOptions> ptrIGLB;
CHECK_SUCCESS( ptrIGLB.CoCreateInstance(CLSID_GlobalOptions) );
CHECK_SUCCESS( ptrIGLB->Set(COMGLB_EXCEPTION_HANDLING, COMGLB_EXCEPTION_DONOT_HANDLE));
// Initialize COM security
CHECK_SUCCESS
(
CoInitializeSecurity
(
NULL, // IN PSECURITY_DESCRIPTOR pSecDesc,
-1, // IN LONG cAuthSvc,
NULL, // IN SOLE_AUTHENTICATION_SERVICE *asAuthSvc,
NULL, // IN void *pReserved1,
RPC_C_AUTHN_LEVEL_CONNECT, // IN DWORD dwAuthnLevel,
RPC_C_IMP_LEVEL_IMPERSONATE, // IN DWORD dwImpLevel,
NULL, // IN void *pAuthList,
EOAC_NONE, // IN DWORD dwCapabilities,
NULL // IN void *pReserved3
)
);
bCoInitializeSucceeded = true;
if ( !AssertPrivilege( SE_BACKUP_NAME ) )
{
wprintf( L"AssertPrivilege returned error, rc:%d\n", GetLastError() );
return 2;
}
pInstance = new CTestVssWriter(lWait);
if (pInstance == NULL)
{
wprintf(L"allocation failure\n");
DebugBreak();
}
bCreated = true;
pInstance->Initialize();
CHECK_SUCCESS(pInstance->Subscribe());
bSubscribed = true;
CComBSTR strSnapshotSetId = "12345678-1234-1234-1234-1234567890ab";
CComPtr<IVssBackupComponents> pvbc;
CHECK_SUCCESS(CreateVssBackupComponents(&pvbc));
CHECK_SUCCESS(pvbc->InitializeForBackup());
CHECK_SUCCESS(pvbc->SetBackupState (true,
false,
VSS_BT_FULL));
unsigned cWriters;
CComPtr<IVssAsync> pAsync;
CHECK_NOFAIL(pvbc->GatherWriterMetadata(&pAsync));
LoopWait(pAsync, 15, L"GatherWriterMetadata");
CHECK_NOFAIL(pvbc->GetWriterMetadataCount(&cWriters));
VSS_ID id;
while(TRUE)
{
hr = pvbc->StartSnapshotSet(&id);
if (hr == S_OK)
break;
if (hr == VSS_E_SNAPSHOT_SET_IN_PROGRESS)
Sleep(1000);
else
CHECK_SUCCESS(hr);
}
for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
{
CComPtr<IVssExamineWriterMetadata> pMetadata;
VSS_ID idInstance;
CHECK_SUCCESS(pvbc->GetWriterMetadata(iWriter, &idInstance, &pMetadata));
VSS_ID idInstanceT;
VSS_ID idWriter;
CComBSTR bstrWriterName;
VSS_USAGE_TYPE usage;
VSS_SOURCE_TYPE source;
CHECK_SUCCESS(pMetadata->GetIdentity (&idInstanceT,
&idWriter,
&bstrWriterName,
&usage,
&source));
wprintf (L"\n\n");
if (memcmp(&idInstance, &idInstanceT, sizeof(VSS_ID)) != 0)
{
wprintf(L"Instance id mismatch\n");
DebugBreak();
}
WCHAR *pwszInstanceId;
WCHAR *pwszWriterId;
UuidToString(&idInstance, &pwszInstanceId);
UuidToString(&idWriter, &pwszWriterId);
wprintf (L"WriterName = %s\n\n"
L" WriterId = %s\n"
L" InstanceId = %s\n"
L" UsageType = %d (%s)\n"
L" SourceType = %d (%s)\n",
bstrWriterName,
pwszWriterId,
pwszInstanceId,
usage,
GetStringFromUsageType (usage),
source,
GetStringFromSourceType (source));
RpcStringFree(&pwszInstanceId);
RpcStringFree(&pwszWriterId);
unsigned cIncludeFiles, cExcludeFiles, cComponents;
CHECK_SUCCESS(pMetadata->GetFileCounts (&cIncludeFiles,
&cExcludeFiles,
&cComponents));
CComBSTR bstrPath;
CComBSTR bstrFilespec;
CComBSTR bstrAlternate;
CComBSTR bstrDestination;
for(unsigned i = 0; i < cIncludeFiles; i++)
{
CComPtr<IVssWMFiledesc> pFiledesc;
CHECK_SUCCESS(pMetadata->GetIncludeFile(i, &pFiledesc));
PrintFiledesc(pFiledesc, L"\n Include File");
}
for(i = 0; i < cExcludeFiles; i++)
{
CComPtr<IVssWMFiledesc> pFiledesc;
CHECK_SUCCESS(pMetadata->GetExcludeFile(i, &pFiledesc));
PrintFiledesc(pFiledesc, L"\n Exclude File");
}
for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
{
CComPtr<IVssWMComponent> pComponent;
PVSSCOMPONENTINFO pInfo;
CHECK_SUCCESS(pMetadata->GetComponent(iComponent, &pComponent));
CHECK_SUCCESS(pComponent->GetComponentInfo(&pInfo));
wprintf (L"\n"
L" Component %d, type = %d (%s)\n"
L" LogicalPath = %s\n"
L" Name = %s\n"
L" Caption = %s\n"
L" Icon size = %u\n",
iComponent,
pInfo->type,
GetStringFromComponentType (pInfo->type),
pInfo->bstrLogicalPath,
pInfo->bstrComponentName,
pInfo->bstrCaption,
pInfo->cbIcon );
wprintf (L" RestoreMetadata = %s\n"
L" NotifyOnBackupComplete = %s\n"
L" Selectable = %s\n",
pInfo->bRestoreMetadata ? L"yes" : L"no",
pInfo->bNotifyOnBackupComplete ? L"yes" : L"no",
pInfo->bSelectable ? L"yes" : L"no");
CHECK_SUCCESS(pvbc->AddComponent (idInstance,
idWriter,
pInfo->type,
pInfo->bstrLogicalPath,
pInfo->bstrComponentName));
if (pInfo->cFileCount > 0)
{
for(i = 0; i < pInfo->cFileCount; i++)
{
CComPtr<IVssWMFiledesc> pFiledesc;
CHECK_SUCCESS(pComponent->GetFile(i, &pFiledesc));
CComBSTR bstrPath;
CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
DoAddToSnapshotSet(pvbc, bstrPath, wszVolumes, rgpSnapshotId, &cSnapshot);
PrintFiledesc(pFiledesc, L" FileGroupFile");
}
}
if (pInfo->cDatabases > 0)
{
for(i = 0; i < pInfo->cDatabases; i++)
{
CComPtr<IVssWMFiledesc> pFiledesc;
CHECK_SUCCESS(pComponent->GetDatabaseFile(i, &pFiledesc));
CComBSTR bstrPath;
CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
DoAddToSnapshotSet(pvbc, bstrPath, wszVolumes, rgpSnapshotId, &cSnapshot);
PrintFiledesc(pFiledesc, L" DatabaseFile");
}
}
if (pInfo->cLogFiles > 0)
{
for(i = 0; i < pInfo->cLogFiles; i++)
{
CComPtr<IVssWMFiledesc> pFiledesc;
CHECK_SUCCESS(pComponent->GetDatabaseLogFile(i, &pFiledesc));
CComBSTR bstrPath;
CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
DoAddToSnapshotSet(pvbc, bstrPath, wszVolumes, rgpSnapshotId, &cSnapshot);
PrintFiledesc(pFiledesc, L" DatabaseLogFile");
}
}
pComponent->FreeComponentInfo(pInfo);
}
VSS_RESTOREMETHOD_ENUM method;
CComBSTR bstrUserProcedure;
CComBSTR bstrService;
VSS_WRITERRESTORE_ENUM writerRestore;
unsigned cMappings;
bool bRebootRequired;
CHECK_NOFAIL(pMetadata->GetRestoreMethod (&method,
&bstrService,
&bstrUserProcedure,
&writerRestore,
&bRebootRequired,
&cMappings));
wprintf (L"\n"
L" Restore method = %d (%s)\n"
L" Service = %s\n"
L" User Procedure = %s\n"
L" WriterRestore = %d (%s)\n"
L" RebootRequired = %s\n",
method,
GetStringFromRestoreMethod (method),
bstrService,
bstrUserProcedure,
writerRestore,
GetStringFromWriterRestoreMethod (writerRestore),
bRebootRequired ? L"yes" : L"no");
for(i = 0; i < cMappings; i++)
{
CComPtr<IVssWMFiledesc> pFiledesc;
CHECK_SUCCESS(pMetadata->GetAlternateLocationMapping(i, &pFiledesc));
PrintFiledesc(pFiledesc, L"AlternateMapping");
}
CComBSTR bstrMetadata;
CHECK_SUCCESS(pMetadata->SaveAsXML(&bstrMetadata));
CComPtr<IVssExamineWriterMetadata> pMetadataNew;
CHECK_SUCCESS(CreateVssExamineWriterMetadata(bstrMetadata, &pMetadataNew));
CHECK_SUCCESS(pMetadataNew->GetIdentity (&idInstanceT,
&idWriter,
&bstrWriterName,
&usage,
&source));
wprintf (L"\n\n");
if (memcmp(&idInstance, &idInstanceT, sizeof(VSS_ID)) != 0)
{
wprintf(L"Instance id mismatch\n");
DebugBreak();
}
UuidToString(&idInstance, &pwszInstanceId);
UuidToString(&idWriter, &pwszWriterId);
wprintf (L"WriterName = %s\n\n"
L" WriterId = %s\n"
L" InstanceId = %s\n"
L" UsageType = %d (%s)\n"
L" SourceType = %d (%s)\n",
bstrWriterName,
pwszWriterId,
pwszInstanceId,
usage,
GetStringFromUsageType (usage),
source,
GetStringFromSourceType (source));
RpcStringFree(&pwszInstanceId);
RpcStringFree(&pwszWriterId);
}
CHECK_SUCCESS(pvbc->FreeWriterMetadata());
{
CComPtr<IVssAsync> pAsync;
HRESULT hr;
CHECK_SUCCESS(pvbc->PrepareForBackup(&pAsync));
LoopWait(pAsync, 5, L"PrepareForBackup");
}
CheckStatus(pvbc, L"After Prepare Backup");
unsigned cWriterComponents;
CHECK_SUCCESS(pvbc->GetWriterComponentsCount(&cWriterComponents));
for(iWriter = 0; iWriter < cWriterComponents; iWriter++)
{
CComPtr<IVssWriterComponentsExt> pWriter;
CHECK_SUCCESS(pvbc->GetWriterComponents(iWriter, &pWriter));
unsigned cComponents;
CHECK_SUCCESS(pWriter->GetComponentCount(&cComponents));
VSS_ID idWriter, idInstance;
CHECK_SUCCESS(pWriter->GetWriterInfo(&idInstance, &idWriter));
for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
{
CComPtr<IVssComponent> pComponent;
CHECK_SUCCESS(pWriter->GetComponent(iComponent, &pComponent));
VSS_COMPONENT_TYPE ct;
CComBSTR bstrLogicalPath;
CComBSTR bstrComponentName;
CHECK_NOFAIL(pComponent->GetLogicalPath(&bstrLogicalPath));
CHECK_SUCCESS(pComponent->GetComponentType(&ct));
CHECK_SUCCESS(pComponent->GetComponentName(&bstrComponentName));
CHECK_SUCCESS(pvbc->SetBackupSucceeded (idInstance,
idWriter,
ct,
bstrLogicalPath,
bstrComponentName,
true));
}
}
{
CComPtr<IVssAsync> pAsync;
INT nPercentDone;
CHECK_SUCCESS(pvbc->DoSnapshotSet (&pAsync));
CHECK_SUCCESS(pAsync->Wait());
CHECK_SUCCESS(pAsync->QueryStatus(&hr, &nPercentDone));
}
if (FAILED(hr))
{
wprintf(L"Creating the snapshot failed. hr = 0x%08lx\n", hr);
CheckStatus(pvbc, L"After Do Snapshot");
}
else
{
CheckStatus(pvbc, L"After Do Snapshot");
CComBSTR bstrXML;
CComPtr<IVssBackupComponents> pvbcRestore;
CHECK_SUCCESS(pvbc->SaveAsXML(&bstrXML));
CHECK_SUCCESS(CreateVssBackupComponents(&pvbcRestore));
CHECK_SUCCESS(pvbcRestore->InitializeForRestore(bstrXML));
wprintf(L"InitializeForRestore succeeded.\n");
LONG lSnapshotsNotDeleted;
VSS_ID rgSnapshotsNotDeleted[10];
{
CComPtr<IVssAsync> pAsync;
HRESULT hr;
CHECK_SUCCESS(pvbc->BackupComplete(&pAsync));
LoopWait(pAsync, 5, L"BackupComplete");
}
CheckStatus(pvbc, L"After Backup Complete");
hr = pvbc->DeleteSnapshots (id,
VSS_OBJECT_SNAPSHOT_SET,
false,
&lSnapshotsNotDeleted,
rgSnapshotsNotDeleted);
if (FAILED(hr))
wprintf(L"Deletion of Snapshots failed. hr = 0x%08lx\n", hr);
{
CComPtr<IVssAsync> pAsync;
HRESULT hr;
pvbcRestore->GatherWriterMetadata(&pAsync);
CHECK_SUCCESS(pAsync->Wait());
CHECK_SUCCESS(pAsync->QueryStatus(&hr, NULL));
CHECK_NOFAIL(hr);
CHECK_SUCCESS(pvbcRestore->GetWriterMetadataCount(&cWriters));
for(iWriter = 0; iWriter < cWriters; iWriter++)
{
CComPtr<IVssExamineWriterMetadata> pMetadata;
VSS_ID idInstance;
CHECK_SUCCESS(pvbcRestore->GetWriterMetadata(iWriter, &idInstance, &pMetadata));
}
pAsync = NULL;
pvbcRestore->PostRestore(&pAsync);
LoopWait(pAsync, 5, L"PostRetore");
CHECK_NOFAIL(hr);
}
}
}
catch(...)
{
BS_ASSERT(FALSE);
hr = E_UNEXPECTED;
}
if (bSubscribed)
pInstance->Unsubscribe();
if (bCreated)
delete pInstance;
if (FAILED(hr))
wprintf(L"Failed with %08x.\n", hr);
if (bCoInitializeSucceeded)
CoUninitialize();
return(0);
}