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.
 
 
 
 
 
 

843 lines
28 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Abstract:
@doc
@module sqlwriter.cpp | Implementation of Writer
@end
Author:
Brian Berkowitz [brianb] 04/17/2000
TBD:
Revision History:
Name Date Comments
brianb 04/17/2000 created
brianb 04/20/2000 integrated with coordinator
brainb 05/05/2000 add OnIdentify support
mikejohn 06/01/2000 fix minor but confusing typos in trace messages
mikejohn 09/19/2000 176860: Add the missing calling convention specifiers
--*/
#include <stdafx.hxx>
#include "vs_inc.hxx"
#include "vs_idl.hxx"
#include <vs_hash.hxx>
#include <base64coder.h>
#include "vswriter.h"
#include "sqlsnap.h"
#include "sqlwriter.h"
#include "vs_seh.hxx"
#include "vs_trace.hxx"
#include "vs_debug.hxx"
#include "allerror.h"
#include "sqlwrtguid.h"
////////////////////////////////////////////////////////////////////////
// Standard foo for file name aliasing. This code block must be after
// all includes of VSS header files.
//
#ifdef VSS_FILE_ALIAS
#undef VSS_FILE_ALIAS
#endif
#define VSS_FILE_ALIAS "SQWWRTRC"
//
////////////////////////////////////////////////////////////////////////
static LPCWSTR x_wszSqlServerWriter = L"SqlServerWriter";
static LPCWSTR s_wszWriterName = L"MSDEWriter";
HRESULT STDMETHODCALLTYPE CSqlWriter::Initialize()
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::Initialize");
try
{
InitSQLEnvironment();
ft.hr = CVssWriter::Initialize
(
WRITERID_SqlWriter,
s_wszWriterName,
VSS_UT_SYSTEMSERVICE,
VSS_ST_TRANSACTEDDB,
VSS_APP_BACK_END,
60000
);
if (ft.HrFailed())
ft.Throw
(
VSSDBG_SQLWRITER,
E_UNEXPECTED,
L"Failed to initialize the Sql writer. hr = 0x%08lx",
ft.hr
);
ft.hr = Subscribe();
if (ft.HrFailed())
ft.Throw
(
VSSDBG_SQLWRITER,
E_UNEXPECTED,
L"Subscribing the Sql server writer failed. hr = %0x08lx",
ft.hr
);
}
VSS_STANDARD_CATCH(ft)
return ft.hr;
}
HRESULT STDMETHODCALLTYPE CSqlWriter::Uninitialize()
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::Uninitialize");
return Unsubscribe();
}
bool STDMETHODCALLTYPE CSqlWriter::OnPrepareBackup
(
IN IVssWriterComponents *pComponents
)
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnPrepareBackup");
LPWSTR *rgwszDB = NULL;
UINT cwszDB = 0;
LPWSTR *rgwszInstances = NULL;
UINT cwszInstances = 0;
bool bSuccess = true;
try
{
// clear existing arrays
if (m_rgwszDatabases)
{
for(UINT i = 0; i < m_cDatabases; i++)
{
delete m_rgwszDatabases[i];
delete m_rgwszInstances[i];
}
delete m_rgwszDatabases;
delete m_rgwszInstances;
m_rgwszDatabases = NULL;
m_rgwszInstances = NULL;
m_cDatabases = 0;
}
m_bComponentsSelected = AreComponentsSelected();
if (m_bComponentsSelected)
{
UINT cComponents;
ft.hr = pComponents->GetComponentCount(&cComponents);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponentCount");
rgwszDB = new LPWSTR[cComponents];
rgwszInstances = new LPWSTR[cComponents];
if (rgwszDB == NULL || rgwszInstances == NULL)
ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"out of memory");
for(UINT iComponent = 0; iComponent < cComponents; iComponent++)
{
CComPtr<IVssComponent> pComponent;
ft.hr = pComponents->GetComponent(iComponent, &pComponent);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponent");
CComBSTR bstrLogicalPath;
CComBSTR bstrDBName;
ft.hr = pComponent->GetLogicalPath(&bstrLogicalPath);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetLogicalPath");
ft.hr = pComponent->GetComponentName(&bstrDBName);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetComponentName");
LPWSTR wszDB = new WCHAR[wcslen(bstrDBName) + 1];
if (wszDB == NULL)
ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"out of memory");
wcscpy(wszDB, bstrDBName);
rgwszDB[cwszDB++] = wszDB;
LPWSTR wszInstance = new WCHAR[wcslen(bstrLogicalPath) + 1];
if (wszInstance == NULL)
ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"out of memory");
wcscpy(wszInstance, bstrLogicalPath);
rgwszInstances[cwszInstances++] = wszInstance;
}
}
m_rgwszDatabases = rgwszDB;
m_rgwszInstances = rgwszInstances;
m_cDatabases = cwszDB;
}
catch(...)
{
for(UINT iwsz = 0; iwsz < cwszDB; iwsz++)
delete rgwszDB[iwsz];
delete rgwszDB;
for(UINT iwsz = 0; iwsz < cwszInstances; iwsz++)
delete rgwszInstances[iwsz];
delete rgwszInstances;
bSuccess = false;
}
return bSuccess;
}
bool STDMETHODCALLTYPE CSqlWriter::OnPrepareSnapshot()
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnPrepareSnapshot");
try
{
BS_ASSERT(!m_fFrozen);
// delete sql snapshot element if it exists
delete m_pSqlSnapshot;
m_pSqlSnapshot = NULL;
m_pSqlSnapshot = CreateSqlSnapshot();
if (m_pSqlSnapshot == NULL)
ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Failed to allocate CSqlSnapshot object.");
ft.hr = m_pSqlSnapshot->Prepare(this);
}
VSS_STANDARD_CATCH(ft)
TranslateWriterError(ft.hr);
return !ft.HrFailed();
}
bool STDMETHODCALLTYPE CSqlWriter::OnFreeze()
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnFreeze");
try
{
BS_ASSERT(!m_fFrozen);
ft.hr = m_pSqlSnapshot->Freeze();
if (!ft.HrFailed())
m_fFrozen = true;
}
VSS_STANDARD_CATCH(ft)
TranslateWriterError(ft.hr);
return !ft.HrFailed();
}
bool STDMETHODCALLTYPE CSqlWriter::OnThaw()
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnThaw");
try
{
if (m_fFrozen)
{
m_fFrozen = false;
ft.hr = m_pSqlSnapshot->Thaw();
}
}
VSS_STANDARD_CATCH(ft)
TranslateWriterError(ft.hr);
return !ft.HrFailed();
}
bool STDMETHODCALLTYPE CSqlWriter::OnPostSnapshot
(
IN IVssWriterComponents *pWriter
)
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"STDMETHODCALLTYPE CSqlWriter::OnPostSnapshot");
// map of databases that were actually successfully frozen
CVssSimpleMap<VSS_PWSZ, FrozenDatabaseInfo *> mapDatabases;
FrozenDatabaseInfo fInfo;
WCHAR *wsz = NULL;
FrozenDatabaseInfo *pfInfo = NULL;
try
{
ft.hr = m_pSqlSnapshot->GetFirstDatabase(&fInfo);
while(ft.hr != DB_S_ENDOFROWSET)
{
// check for error code
if (ft.HrFailed())
ft.Throw
(
VSSDBG_SQLWRITER,
E_UNEXPECTED,
L"Enumerating database servers failed. hr = 0x%08lx",
ft.hr
);
wsz = (WCHAR *) new WCHAR[wcslen(fInfo.serverName) + wcslen(fInfo.databaseName) + 2];
pfInfo = new FrozenDatabaseInfo;
if (wsz == NULL || pfInfo == NULL)
ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Cannot allocate frozen info mapping.");
// name is server\database
wcscpy(wsz, fInfo.serverName);
wcscat(wsz, L"\\");
wcscat(wsz, fInfo.databaseName);
memcpy(pfInfo, &fInfo, sizeof(fInfo));
if (!mapDatabases.Add(wsz, pfInfo))
ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Cannot allocate frozen info mapping.");
// ownership is transfered to the map
wsz = NULL;
pfInfo = NULL;
ft.hr = m_pSqlSnapshot->GetNextDatabase(&fInfo);
}
UINT cComponents;
ft.hr = pWriter->GetComponentCount(&cComponents);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponentCount");
// loop through components supplied by the user.
for(UINT iComponent = 0; iComponent < cComponents; iComponent++)
{
WCHAR wszName[MAX_SERVERNAME + MAX_DBNAME + 1];
CComPtr<IVssComponent> pComponent;
ft.hr = pWriter->GetComponent(iComponent, &pComponent);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponent");
VSS_COMPONENT_TYPE ct;
ft.hr = pComponent->GetComponentType(&ct);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetComponentType");
if (ct != VSS_CT_DATABASE)
ft.Throw(VSSDBG_SQLWRITER, VSS_E_WRITERERROR_NONRETRYABLE, L"requesting a non-database component");
CComBSTR bstrLogicalPath;
ft.hr = pComponent->GetLogicalPath(&bstrLogicalPath);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetLogicalPath");
CComBSTR bstrComponentName;
ft.hr = pComponent->GetComponentName(&bstrComponentName);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterCokmponents::GetComponentName");
wcscpy(wszName, bstrLogicalPath);
wcscat(wszName, L"\\");
wcscat(wszName, bstrComponentName);
FrozenDatabaseInfo *pfInfoFound = mapDatabases.Lookup(wszName);
if (pfInfoFound == NULL)
ft.Throw(VSSDBG_SQLWRITER, VSS_E_WRITERERROR_RETRYABLE, L"database was not successfully snapshotted");
Base64Coder coder;
coder.Encode(pfInfoFound->pMetaData, pfInfoFound->metaDataSize);
ft.hr = pComponent->SetBackupMetadata(coder.EncodedMessage());
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::SetBackupMetadata");
}
}
VSS_STANDARD_CATCH(ft)
int cBuckets = mapDatabases.GetSize();
for(int iBucket = 0; iBucket < cBuckets; iBucket++)
{
delete mapDatabases.GetKeyAt(iBucket);
delete mapDatabases.GetValueAt(iBucket);
}
delete wsz;
delete pfInfo;
delete m_pSqlSnapshot;
m_pSqlSnapshot = NULL;
TranslateWriterError(ft.hr);
return !ft.HrFailed();
}
bool STDMETHODCALLTYPE CSqlWriter::OnAbort()
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnAbort");
try
{
if (m_fFrozen)
{
m_fFrozen = false;
ft.hr = m_pSqlSnapshot->Thaw();
}
delete m_pSqlSnapshot;
m_pSqlSnapshot = NULL;
}
VSS_STANDARD_CATCH(ft)
return !ft.HrFailed();
}
bool CSqlWriter::IsPathInSnapshot(const WCHAR *wszPath) throw()
{
return IsPathAffected(wszPath);
}
// returns whether backup supports component based backup/restore
bool CSqlWriter::IsComponentBased()
{
return m_bComponentsSelected;
}
// enumerate selected databases for a given instance, pNextIndex indicates the
// next instance to look for. 0 indicates find first instance
LPCWSTR CSqlWriter::EnumerateSelectedDatabases(LPCWSTR wszInstanceName, UINT *pNextIndex)
{
// should only be called for component based backups
BS_ASSERT(m_bComponentsSelected);
BS_ASSERT(pNextIndex);
if (!m_bComponentsSelected)
return NULL;
// starting point in array
UINT iwsz = *pNextIndex;
// loop until a matching instance is found
for(iwsz; iwsz < m_cDatabases; iwsz++)
{
if (wcscmp(wszInstanceName, m_rgwszInstances[iwsz]) == 0)
break;
}
if (iwsz >= m_cDatabases)
{
// no more matching entries
*pNextIndex = m_cDatabases;
return NULL;
}
// seach should start at next database entry
*pNextIndex = iwsz + 1;
// return current database name
return m_rgwszDatabases[iwsz];
}
// handle request for WRITER_METADATA
// implements CVssWriter::OnIdentify
bool STDMETHODCALLTYPE CSqlWriter::OnIdentify(IVssCreateWriterMetadata *pMetadata)
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnIdentify");
ServerInfo server;
DatabaseInfo database;
DatabaseFileInfo file;
// create enumerator
CSqlEnumerator *pEnumServers = NULL;
CSqlEnumerator *pEnumDatabases = NULL;
CSqlEnumerator *pEnumFiles = NULL;
try
{
ft.hr = pMetadata->SetRestoreMethod
(
VSS_RME_RESTORE_IF_CAN_REPLACE,
NULL,
NULL,
VSS_WRE_ALWAYS,
false
);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssCreateWriterMetadata::SetRestoreMethod");
pEnumServers = CreateSqlEnumerator();
if (pEnumServers == NULL)
ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Failed to create CSqlEnumerator");
// find first server
ft.hr = pEnumServers->FirstServer(&server);
while(ft.hr != DB_S_ENDOFROWSET)
{
// check for error code
if (ft.HrFailed())
ft.Throw
(
VSSDBG_SQLWRITER,
E_UNEXPECTED,
L"Enumerating database servers failed. hr = 0x%08lx",
ft.hr
);
// only look at server if it is online
if (server.isOnline)
{
// recreate enumerator for databases
BS_ASSERT(pEnumDatabases == NULL);
pEnumDatabases = CreateSqlEnumerator();
if (pEnumDatabases == NULL)
ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Failed to create CSqlEnumerator");
// find first database
ft.hr = pEnumDatabases->FirstDatabase(server.name, &database);
while(ft.hr != DB_S_ENDOFROWSET)
{
// check for error
if (ft.HrFailed())
ft.Throw
(
VSSDBG_SQLWRITER,
E_UNEXPECTED,
L"Enumerating databases failed. hr = 0x%08lx",
ft.hr
);
// only include database if it supports Freeze and
// don't include the tempdb
if (wcscmp(database.name, L"tempdb") != 0 &&
database.supportsFreeze)
{
// add database component
ft.hr = pMetadata->AddComponent
(
VSS_CT_DATABASE, // component type
server.name, // logical path
database.name, // component name
NULL, // caption
NULL, // pbIcon
0, // cbIcon
false, // bRestoreMetadata
false, // bNotifyOnBackupComplete
true // bSelectable
);
if (ft.HrFailed())
ft.Throw
(
VSSDBG_SQLWRITER,
E_UNEXPECTED,
L"IVssCreateWriterMetadata::AddComponent failed. hr = 0x%08lx",
ft.hr
);
// recreate enumerator for files
BS_ASSERT(pEnumFiles == NULL);
pEnumFiles = CreateSqlEnumerator();
if (pEnumFiles == NULL)
ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Failed to create CSqlEnumerator");
// findfirst database file
ft.hr = pEnumFiles->FirstFile(server.name, database.name, &file);
while(ft.hr != DB_S_ENDOFROWSET)
{
// check for error
if (ft.HrFailed())
ft.Throw
(
VSSDBG_SQLWRITER,
E_UNEXPECTED,
L"Enumerating database files failed. hr = 0x%08lx",
ft.hr
);
// split file name into separate path
// and filename components. Path is everything
// before the last backslash.
WCHAR logicalPath[MAX_PATH];
WCHAR *pFileName = file.name + wcslen(file.name);
while(--pFileName > file.name)
{
if (*pFileName == '\\')
break;
}
// if no backslash, then there is no path
if (pFileName == file.name)
logicalPath[0] = '\0';
else
{
// extract path
size_t cwc = wcslen(file.name) - wcslen(pFileName);
memcpy(logicalPath, file.name, cwc*sizeof(WCHAR));
logicalPath[cwc] = L'\0';
pFileName++;
}
if (file.isLogFile)
// log file
ft.hr = pMetadata->AddDatabaseLogFiles
(
server.name,
database.name,
logicalPath,
pFileName
);
else
// physical database file
ft.hr = pMetadata->AddDatabaseFiles
(
server.name,
database.name,
logicalPath,
pFileName
);
// continue at next file
ft.hr = pEnumFiles->NextFile(&file);
}
delete pEnumFiles;
pEnumFiles = NULL;
}
// continue at next database
ft.hr = pEnumDatabases->NextDatabase(&database);
}
delete pEnumDatabases;
pEnumDatabases = NULL;
}
// continue at next server
ft.hr = pEnumServers->NextServer(&server);
}
}
VSS_STANDARD_CATCH(ft)
TranslateWriterError(ft.hr);
delete pEnumServers;
delete pEnumDatabases;
delete pEnumFiles;
return ft.HrFailed() ? false : true;
}
// translate a sql writer error code into a writer error
void CSqlWriter::TranslateWriterError(HRESULT hr)
{
if (SUCCEEDED(hr))
return;
switch(hr)
{
default:
SetWriterFailure(VSS_E_WRITERERROR_NONRETRYABLE);
break;
case S_OK:
break;
case E_OUTOFMEMORY:
case HRESULT_FROM_WIN32(ERROR_DISK_FULL):
case HRESULT_FROM_WIN32(ERROR_TOO_MANY_OPEN_FILES):
case HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY):
case HRESULT_FROM_WIN32(ERROR_NO_MORE_USER_HANDLES):
SetWriterFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
break;
case HRESULT_FROM_WIN32(E_SQLLIB_TORN_DB):
SetWriterFailure(VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT);
break;
}
}
bool STDMETHODCALLTYPE CSqlWriter::OnPreRestore
(
IN IVssWriterComponents *pWriter
)
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnPreRestore");
try
{
// delete sql restore element if it exists
delete m_pSqlRestore;
m_pSqlRestore = NULL;
UINT cComponents;
ft.hr = pWriter->GetComponentCount(&cComponents);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponentCount");
if (cComponents == 0)
return true;
for(UINT iComponent = 0; iComponent < cComponents; iComponent++)
{
CComPtr<IVssComponent> pComponent;
ft.hr = pWriter->GetComponent(iComponent, &pComponent);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponent");
bool bSelectedForRestore;
ft.hr = pComponent->IsSelectedForRestore(&bSelectedForRestore);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::IsSelectedForRestore");
if (!bSelectedForRestore)
continue;
if (m_pSqlRestore == NULL)
{
m_pSqlRestore = CreateSqlRestore();
if (m_pSqlRestore == NULL)
ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"cannot allocate CSqlRestore object");
}
VSS_COMPONENT_TYPE ct;
ft.hr = pComponent->GetComponentType(&ct);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetComponentType");
if (ct != VSS_CT_DATABASE)
ft.Throw(VSSDBG_SQLWRITER, VSS_E_WRITERERROR_NONRETRYABLE, L"requesting a non-database component");
CComBSTR bstrLogicalPath;
ft.hr = pComponent->GetLogicalPath(&bstrLogicalPath);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetLogicalPath");
CComBSTR bstrComponentName;
ft.hr = pComponent->GetComponentName(&bstrComponentName);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterCokmponents::GetComponentName");
ft.hr = m_pSqlRestore->PrepareToRestore(bstrLogicalPath, bstrComponentName);
if (ft.HrFailed())
{
WCHAR wsz[128];
swprintf(wsz, L"CSqlRestor::PrepareToRestore failed with HRESULT = 0x%08lx", ft.hr);
ft.hr = pComponent->SetPreRestoreFailureMsg(wsz);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::SetPreRestoreFailureMsg");
}
}
}
VSS_STANDARD_CATCH(ft)
return true;
}
bool STDMETHODCALLTYPE CSqlWriter::OnPostRestore
(
IN IVssWriterComponents *pWriter
)
{
CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnPostRestore");
try
{
if (m_pSqlRestore == NULL)
return true;
UINT cComponents;
ft.hr = pWriter->GetComponentCount(&cComponents);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponentCount");
for(UINT iComponent = 0; iComponent < cComponents; iComponent++)
{
CComPtr<IVssComponent> pComponent;
ft.hr = pWriter->GetComponent(iComponent, &pComponent);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponent");
bool bSelectedForRestore;
ft.hr = pComponent->IsSelectedForRestore(&bSelectedForRestore);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::IsSelectedForRestore");
if (!bSelectedForRestore)
continue;
VSS_COMPONENT_TYPE ct;
ft.hr = pComponent->GetComponentType(&ct);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetComponentType");
if (ct != VSS_CT_DATABASE)
ft.Throw(VSSDBG_SQLWRITER, VSS_E_WRITERERROR_NONRETRYABLE, L"requesting a non-database component");
CComBSTR bstrLogicalPath;
ft.hr = pComponent->GetLogicalPath(&bstrLogicalPath);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetLogicalPath");
CComBSTR bstrComponentName;
ft.hr = pComponent->GetComponentName(&bstrComponentName);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterCokmponents::GetComponentName");
CComBSTR bstrPreRestoreFailure;
ft.hr = pComponent->GetPreRestoreFailureMsg(&bstrPreRestoreFailure);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetPreRestoreFailureMsg");
// if we got an error during prerestore don't do a post restore
if (bstrPreRestoreFailure)
continue;
bool bAdditionalRestores;
ft.hr = pComponent->GetAdditionalRestores(&bAdditionalRestores);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetAdditionalRestores");
CComBSTR bstrMetadata;
ft.hr = pComponent->GetBackupMetadata(&bstrMetadata);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetBackupMetadata");
Base64Coder coder;
coder.Decode(bstrMetadata);
BYTE *pbVal = coder.DecodedMessage();
ft.hr = m_pSqlRestore->FinalizeRestore
(
bstrLogicalPath,
bstrComponentName,
bAdditionalRestores,
pbVal + sizeof(UINT),
*(UINT *) pbVal
);
if (ft.HrFailed())
{
WCHAR wsz[128];
swprintf(wsz, L"CSqlRestore::FinalizeRestore failed with HRESULT = 0x%08lx", ft.hr);
ft.hr = pComponent->SetPostRestoreFailureMsg(wsz);
ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::SetPreRestoreFailureMsg");
}
}
}
VSS_STANDARD_CATCH(ft)
return true;
}