/* **++ ** ** 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; nIndexInitializeForBackup()); 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 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 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 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 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 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 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 pFiledesc; CHECK_SUCCESS (pMetadata->GetIncludeFile (i, &pFiledesc)); PrintFiledesc(pFiledesc, L"\n Include File"); } for(i = 0; i < cExcludeFiles; i++) { CComPtr pFiledesc; CHECK_SUCCESS (pMetadata->GetExcludeFile (i, &pFiledesc)); PrintFiledesc (pFiledesc, L"\n Exclude File"); } for(unsigned iComponent = 0; iComponent < cComponents; iComponent++) { CComPtr 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 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 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 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 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 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(); }