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.
514 lines
16 KiB
514 lines
16 KiB
/*
|
|
**++
|
|
**
|
|
** Copyright (c) 2000-2001 Microsoft Corporation
|
|
**
|
|
**
|
|
** Module Name:
|
|
**
|
|
** vsreq.cpp
|
|
**
|
|
**
|
|
** Abstract:
|
|
**
|
|
** Sample program to
|
|
** - obtain and display the Writer metadata.
|
|
** - create a snapshot set
|
|
**
|
|
** Author:
|
|
**
|
|
** Adi Oltean [aoltean] 05-Dec-2000
|
|
**
|
|
** The sample is based on the Metasnap test program written by Michael C. Johnson.
|
|
**
|
|
**
|
|
** Revision History:
|
|
**
|
|
**--
|
|
*/
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Includes
|
|
|
|
#include "vsreq.h"
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Processing functions
|
|
|
|
CVssSampleRequestor::CVssSampleRequestor()
|
|
{
|
|
// Initialize data members
|
|
m_bCoInitializeSucceeded = false;
|
|
m_bBootableSystemState = false;
|
|
m_bComponentSelectionEnabled = false;
|
|
m_pBackupComponents = NULL;
|
|
m_nVolumesCount = 0;
|
|
m_hr = S_OK;
|
|
m_pwszXmlFile = NULL;
|
|
m_pXmlFile = NULL;
|
|
|
|
// For safety
|
|
for (int nIndex=0; nIndex<MAX_VOLUMES; nIndex++) {
|
|
m_ppwszVolumesList[nIndex] = NULL;
|
|
m_ppwszVolumeNamesList[nIndex] = NULL;
|
|
}
|
|
|
|
// Print display header
|
|
wprintf(L"\nVSS Requestor Sample application, version 1.0\n");
|
|
}
|
|
|
|
|
|
CVssSampleRequestor::~CVssSampleRequestor()
|
|
{
|
|
// Deallocate some internal strings
|
|
delete m_pwszXmlFile;
|
|
|
|
// delete the allocated volumes
|
|
for (int nIndex=0; nIndex<m_nVolumesCount; nIndex++) {
|
|
free(m_ppwszVolumesList[nIndex]);
|
|
free(m_ppwszVolumeNamesList[nIndex]);
|
|
}
|
|
|
|
// Close the Xml file
|
|
if (m_pXmlFile)
|
|
fclose(m_pXmlFile);
|
|
|
|
// Releasing backup components prior to the CoUninitialize call
|
|
m_pBackupComponents = NULL;
|
|
|
|
// Unloading the COM library
|
|
if (m_bCoInitializeSucceeded)
|
|
CoUninitialize();
|
|
}
|
|
|
|
|
|
void CVssSampleRequestor::Initialize()
|
|
{
|
|
wprintf (L"\n----------------- Initializing ---------------------\n");
|
|
|
|
// Initialize COM library
|
|
CHECK_NOFAIL(CoInitializeEx (NULL, COINIT_MULTITHREADED));
|
|
m_bCoInitializeSucceeded = true;
|
|
wprintf (L"COM library initialized.\n");
|
|
|
|
// 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
|
|
)
|
|
);
|
|
wprintf (L"COM security initialized.\n");
|
|
|
|
// Open the Xml file
|
|
if (m_pwszXmlFile) {
|
|
m_pXmlFile = _wfopen( m_pwszXmlFile, L"w");
|
|
if (!m_pXmlFile)
|
|
Error(1, L"\nError creating/opening the file %s\n", m_pwszXmlFile);
|
|
wprintf (L"XML results file created: %s\n", m_pwszXmlFile);
|
|
}
|
|
|
|
// Create the Backup components object
|
|
CHECK_NOFAIL(CreateVssBackupComponents(&m_pBackupComponents));
|
|
wprintf (L"Backup components object created.\n");
|
|
|
|
// Initialize the backup components object for backup
|
|
CHECK_NOFAIL(m_pBackupComponents->InitializeForBackup());
|
|
CHECK_SUCCESS(m_pBackupComponents->SetBackupState(
|
|
m_bComponentSelectionEnabled, m_bBootableSystemState, VSS_BT_FULL));
|
|
wprintf (L"Backup components object initialized for backup operations.\n");
|
|
}
|
|
|
|
|
|
void CVssSampleRequestor::CreateSnapshotSet()
|
|
{
|
|
CComPtr<IVssAsync> pAsync;
|
|
VSS_ID SnapshotsArray[MAX_VOLUMES];
|
|
VSS_ID SnapshotSetId = GUID_NULL;
|
|
|
|
wprintf (L"\n---------- Starting backup/snapshot ----------------\n");
|
|
|
|
// Starting a new snapshot set
|
|
wprintf(L"Starting a new Snapshot Set\n");
|
|
CHECK_SUCCESS(m_pBackupComponents->StartSnapshotSet(&SnapshotSetId));
|
|
wprintf(L"Snapshot Set created with ID = " WSTR_GUID_FMT L"\n", GUID_PRINTF_ARG(SnapshotSetId));
|
|
|
|
// Add volumes to the snapshot set
|
|
wprintf(L"Adding volumes to the Snapshot Set: \n");
|
|
for (INT nIndex = 0; nIndex < m_nVolumesCount; nIndex++)
|
|
{
|
|
// Get the volume containing the path
|
|
wprintf(L"\t- Adding volume containing %s ... ", m_ppwszVolumesList[nIndex] );
|
|
|
|
// Add the volume to the snapshot set
|
|
CHECK_SUCCESS(m_pBackupComponents->AddToSnapshotSet(m_ppwszVolumesList[nIndex],
|
|
GUID_NULL, &(SnapshotsArray[nIndex])));
|
|
wprintf( L"OK\n");
|
|
}
|
|
|
|
wprintf (L"\n------------ Creating the snapshot -----------------\n");
|
|
|
|
// Prepare for backup
|
|
wprintf(L"Starting asynchronous PrepareForBackup. Please wait...\n");
|
|
HRESULT hr = S_OK;
|
|
CHECK_SUCCESS(m_pBackupComponents->PrepareForBackup(&pAsync));
|
|
CHECK_SUCCESS(pAsync->Wait());
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hr, NULL));
|
|
CHECK_NOFAIL((hr));
|
|
wprintf(L"Asynchronous PrepareForBackup finished.\n");
|
|
pAsync = NULL;
|
|
|
|
// Gather writer status
|
|
GatherWriterStatus(L"after PrepareForBackup");
|
|
|
|
// Create the snapshot
|
|
wprintf(L"\nStarting asynchronous DoSnapshotSet. Please wait...\n");
|
|
hr = S_OK;
|
|
CHECK_SUCCESS(m_pBackupComponents->DoSnapshotSet(&pAsync));
|
|
CHECK_SUCCESS(pAsync->Wait());
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hr, NULL));
|
|
CHECK_NOFAIL((hr));
|
|
wprintf(L"Asynchronous DoSnapshotSet finished.\n");
|
|
pAsync = NULL;
|
|
|
|
// Gather writer status
|
|
GatherWriterStatus(L"after DoSnapshotSet");
|
|
|
|
wprintf(L"Snapshot set created\n");
|
|
for (INT nIndex = 0; nIndex < m_nVolumesCount; nIndex++)
|
|
{
|
|
VSS_SNAPSHOT_PROP prop;
|
|
CHECK_SUCCESS(m_pBackupComponents->GetSnapshotProperties(SnapshotsArray[nIndex], &prop));
|
|
wprintf(L"\t- The snapshot on volume %s resides at %s\n",
|
|
m_ppwszVolumesList[nIndex], prop.m_pwszSnapshotDeviceObject);
|
|
VssFreeSnapshotProperties(&prop);
|
|
}
|
|
}
|
|
|
|
|
|
void CVssSampleRequestor::BackupComplete()
|
|
{
|
|
unsigned cWriterComponents;
|
|
CComPtr<IVssAsync> pAsync;
|
|
|
|
wprintf (L"\n------------ Completing backup phase ---------------\n");
|
|
|
|
CHECK_SUCCESS(m_pBackupComponents->GetWriterComponentsCount(&cWriterComponents));
|
|
|
|
// If component selection enabled,
|
|
if (m_bComponentSelectionEnabled)
|
|
{
|
|
wprintf(L"Setting the succeeded state for the following components:\n");
|
|
// For each component, mark the completion state as succeeded
|
|
for(unsigned iWriter = 0; iWriter < cWriterComponents; iWriter++)
|
|
{
|
|
CComPtr<IVssWriterComponentsExt> pWriter;
|
|
CHECK_SUCCESS(m_pBackupComponents->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));
|
|
wprintf(L"\t- %s\n", (LPWSTR)bstrComponentName);
|
|
|
|
CHECK_SUCCESS(m_pBackupComponents->SetBackupSucceeded (idInstance,
|
|
idWriter,
|
|
ct,
|
|
bstrLogicalPath,
|
|
bstrComponentName,
|
|
true));
|
|
}
|
|
}
|
|
wprintf(L"\n");
|
|
}
|
|
|
|
// Save the XML file, if needed
|
|
// The contents will be needed at restore, in the InitializeForRestore method.
|
|
if (m_pXmlFile) {
|
|
CComBSTR bstrXML;
|
|
CHECK_SUCCESS(m_pBackupComponents->SaveAsXML(&bstrXML));
|
|
fwprintf( m_pXmlFile, L"%s", (WCHAR*)bstrXML);
|
|
wprintf(L"XML results written in %s\n", m_pwszXmlFile);
|
|
}
|
|
|
|
// Send the BackupComplete event
|
|
wprintf(L"\nStarting asynchronous BackupComplete. Please wait...\n");
|
|
HRESULT hr = S_OK;
|
|
CHECK_SUCCESS(m_pBackupComponents->BackupComplete(&pAsync));
|
|
CHECK_SUCCESS(pAsync->Wait());
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hr, NULL));
|
|
CHECK_NOFAIL((hr));
|
|
wprintf(L"Asynchronous BackupComplete finished.\n");
|
|
pAsync = NULL;
|
|
|
|
// Gather writer status
|
|
GatherWriterStatus(L"after BackupComplete");
|
|
}
|
|
|
|
|
|
// Gather writera metadata and select components for backup, if needed
|
|
void CVssSampleRequestor::GatherWriterMetadata()
|
|
{
|
|
unsigned cWriters;
|
|
CComPtr<IVssAsync> pAsync;
|
|
|
|
wprintf (L"\n---------- Gathering writer metadata ---------------\n");
|
|
|
|
wprintf(L"Starting asynchronous GatherWriterMetadata. Please wait...\n");
|
|
HRESULT hr = S_OK;
|
|
CHECK_SUCCESS(m_pBackupComponents->GatherWriterMetadata(&pAsync));
|
|
CHECK_SUCCESS(pAsync->Wait());
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hr, NULL));
|
|
CHECK_NOFAIL((hr));
|
|
wprintf(L"Asynchronous GatherWriterMetadata finished.\n");
|
|
pAsync = NULL;
|
|
|
|
CHECK_NOFAIL (m_pBackupComponents->GetWriterMetadataCount (&cWriters));
|
|
wprintf(L"Number of writers that responded: %u\n", cWriters);
|
|
|
|
for (unsigned iWriter = 0; iWriter < cWriters; iWriter++)
|
|
{
|
|
CComPtr<IVssExamineWriterMetadata> pMetadata;
|
|
|
|
VSS_ID idInstance;
|
|
VSS_ID idInstanceT;
|
|
VSS_ID idWriter;
|
|
CComBSTR bstrWriterName;
|
|
VSS_USAGE_TYPE usage;
|
|
VSS_SOURCE_TYPE source;
|
|
unsigned cIncludeFiles, cExcludeFiles, cComponents;
|
|
CComBSTR bstrPath;
|
|
CComBSTR bstrFilespec;
|
|
CComBSTR bstrAlternate;
|
|
CComBSTR bstrDestination;
|
|
|
|
CHECK_SUCCESS (m_pBackupComponents->GetWriterMetadata(iWriter, &idInstance, &pMetadata));
|
|
|
|
CHECK_SUCCESS (pMetadata->GetIdentity (&idInstanceT,
|
|
&idWriter,
|
|
&bstrWriterName,
|
|
&usage,
|
|
&source));
|
|
|
|
wprintf (L"\n*** WriterName = %s\n\n"
|
|
L" WriterId = "WSTR_GUID_FMT L"\n"
|
|
L" InstanceId = "WSTR_GUID_FMT L"\n"
|
|
L" UsageType = %d (%s)\n"
|
|
L" SourceType = %d (%s)\n",
|
|
bstrWriterName,
|
|
GUID_PRINTF_ARG(idWriter),
|
|
GUID_PRINTF_ARG(idInstance),
|
|
usage,
|
|
GetStringFromUsageType (usage),
|
|
source,
|
|
GetStringFromSourceType (source));
|
|
|
|
CHECK_SUCCESS(pMetadata->GetFileCounts (&cIncludeFiles,
|
|
&cExcludeFiles,
|
|
&cComponents));
|
|
|
|
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",
|
|
iComponent,
|
|
pInfo->type,
|
|
GetStringFromComponentType (pInfo->type),
|
|
pInfo->bstrLogicalPath,
|
|
pInfo->bstrComponentName,
|
|
pInfo->bstrCaption);
|
|
|
|
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");
|
|
|
|
// If specified, add this component to the backup
|
|
// Remark: A real backup app will first get from the user the list of components to be added
|
|
if (m_bComponentSelectionEnabled) {
|
|
CHECK_SUCCESS(m_pBackupComponents->AddComponent(idInstance,
|
|
idWriter,
|
|
pInfo->type,
|
|
pInfo->bstrLogicalPath,
|
|
pInfo->bstrComponentName));
|
|
|
|
wprintf (L" [Component %d was added to the backup]\n", iComponent);
|
|
}
|
|
|
|
for(i = 0; i < pInfo->cFileCount; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
CHECK_SUCCESS (pComponent->GetFile (i, &pFiledesc));
|
|
PrintFiledesc (pFiledesc, L" FileGroupFile");
|
|
|
|
// If we add the component, snapshot also the volume on which the file reside
|
|
if (m_bComponentSelectionEnabled)
|
|
AddVolumeForComponent(pFiledesc);
|
|
}
|
|
|
|
for(i = 0; i < pInfo->cDatabases; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
CHECK_SUCCESS (pComponent->GetDatabaseFile (i, &pFiledesc));
|
|
PrintFiledesc (pFiledesc, L" DatabaseFile");
|
|
|
|
// If we add the component, snapshot also the volume on which the file reside
|
|
if (m_bComponentSelectionEnabled)
|
|
AddVolumeForComponent(pFiledesc);
|
|
|
|
}
|
|
|
|
|
|
for(i = 0; i < pInfo->cLogFiles; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
CHECK_SUCCESS (pComponent->GetDatabaseLogFile (i, &pFiledesc));
|
|
PrintFiledesc (pFiledesc, L" DatabaseLogFile");
|
|
|
|
// If we add the component, snapshot also the volume on which the file reside
|
|
if (m_bComponentSelectionEnabled)
|
|
AddVolumeForComponent(pFiledesc);
|
|
}
|
|
|
|
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 = %d\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");
|
|
}
|
|
}
|
|
|
|
// Gather writer status
|
|
GatherWriterStatus(L"after GatherWriterMetadata");
|
|
|
|
CHECK_SUCCESS (m_pBackupComponents->FreeWriterMetadata());
|
|
}
|
|
|
|
|
|
void CVssSampleRequestor::GatherWriterStatus(
|
|
IN LPCWSTR wszWhen
|
|
)
|
|
{
|
|
unsigned cWriters;
|
|
CComPtr<IVssAsync> pAsync;
|
|
|
|
wprintf (L"\nGathering writer status %s... ", wszWhen);
|
|
HRESULT hr = S_OK;
|
|
CHECK_SUCCESS(m_pBackupComponents->GatherWriterStatus(&pAsync));
|
|
CHECK_SUCCESS(pAsync->Wait());
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hr, NULL));
|
|
CHECK_NOFAIL((hr));
|
|
CHECK_NOFAIL(m_pBackupComponents->GetWriterStatusCount(&cWriters));
|
|
wprintf (L"%d writers responded\n", cWriters);
|
|
|
|
for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
|
|
{
|
|
VSS_ID idInstance;
|
|
VSS_ID idWriter;
|
|
VSS_WRITER_STATE eWriterStatus;
|
|
CComBSTR bstrWriter;
|
|
HRESULT hrWriterFailure;
|
|
|
|
CHECK_SUCCESS(m_pBackupComponents->GetWriterStatus (iWriter,
|
|
&idInstance,
|
|
&idWriter,
|
|
&bstrWriter,
|
|
&eWriterStatus,
|
|
&hrWriterFailure));
|
|
|
|
WCHAR wszWriterFailure[MAX_TEXT_BUFFER];
|
|
if (hrWriterFailure)
|
|
swprintf(wszWriterFailure, L" Writer error code: %s [0x%08lx]",
|
|
GetStringFromFailureType(hrWriterFailure), hrWriterFailure);
|
|
else
|
|
wszWriterFailure[0] = L'\0';
|
|
|
|
wprintf (L"\t- %s status for writer '%s'. %s\n",
|
|
GetStringFromWriterStatus(eWriterStatus), bstrWriter, wszWriterFailure);
|
|
}
|
|
|
|
m_pBackupComponents->FreeWriterStatus();
|
|
}
|
|
|
|
|