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.
 
 
 
 
 
 

771 lines
22 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Abstract:
@doc
@module VsWriter.cpp | Implementation of Writer
@end
Author:
Adi Oltean [aoltean] 02/02/2000
TBD:
Add comments.
Revision History:
Name Date Comments
brianb 03/28/2000 Created
mikejohn 05/18/2000 ~CVssWriter() should check that wrapper exists
before calling it
mikejohn 06/23/2000 Add external entry point for SetWriterFailure()
mikejohn 09/01/2000 Add extra tracing to identify writers in trace output
mikejohn 09/18/2000 176860: Added calling convention methods where missing
ssteiner 02/14/2001 Changed class interface to version 2.
--*/
#include <stdafx.h>
#include "vs_inc.hxx"
#include "vs_sec.hxx"
#include "vs_idl.hxx"
#include "vs_reg.hxx"
#include "comadmin.hxx"
#include "vswriter.h"
#include "vsevent.h"
#include "vsbackup.h"
#include "vswrtimp.h"
#include "vs_wmxml.hxx"
#include "vs_cmxml.hxx"
extern WCHAR g_ComponentMetadataXML[];
static LPCWSTR x_wszElementRoot = L"root";
static LPCWSTR x_wszElementSnapshotSetDescription = L"SNAPSHOT_SET_DESCRIPTION";
static LPCWSTR x_wszAttrSnapshotSetId = L"snapshotSetId";
static LPCWSTR x_wszAttrXmlns = L"xmlns";
static LPCWSTR x_wszValueXmlns = L"x-schema:#VssComponentMetadata";
static LPCWSTR x_wszAttrContext = L"context";
////////////////////////////////////////////////////////////////////////
// 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 "WSHVWRTC"
//
////////////////////////////////////////////////////////////////////////
static 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);
}
static 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);
}
static LPCWSTR GetStringFromAlternateWriterState (VSS_ALTERNATE_WRITER_STATE aws)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (aws)
{
case VSS_AWS_UNDEFINED: pwszRetString = L"Undefined"; break;
case VSS_AWS_NO_ALTERNATE_WRITER: pwszRetString = L"No alternate writer"; break;
case VSS_AWS_ALTERNATE_WRITER_EXISTS: pwszRetString = L"Alternate writer exists"; break;
case VSS_AWS_THIS_IS_ALTERNATE_WRITER: pwszRetString = L"This is the alternate writer"; break;
default:
break;
}
return (pwszRetString);
}
static LPCWSTR GetStringFromApplicationLevel (VSS_APPLICATION_LEVEL eApplicationLevel)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eApplicationLevel)
{
case VSS_APP_UNKNOWN: pwszRetString = L"Unknown"; break;
case VSS_APP_SYSTEM: pwszRetString = L"System"; break;
case VSS_APP_BACK_END: pwszRetString = L"BackEnd"; break;
case VSS_APP_FRONT_END: pwszRetString = L"FrontEnd"; break;
case VSS_APP_AUTO: pwszRetString = L"Automatic"; break;
default:
break;
}
return (pwszRetString);
}
// constructor
__declspec(dllexport)
STDMETHODCALLTYPE CVssWriter::CVssWriter() :
m_pWrapper(NULL)
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::CVssWriter");
ft.Trace(VSSDBG_GEN, L"**** Constructor: THIS = %p", this);
}
// destructor
__declspec(dllexport)
STDMETHODCALLTYPE CVssWriter::~CVssWriter()
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::CVssWriter");
ft.Trace(VSSDBG_GEN, L"**** Destructor: THIS = %p", this);
if (NULL != m_pWrapper)
{
ft.Trace(VSSDBG_GEN, L"**** Calling CVssWriter::Uninitialize() [%p]", this);
m_pWrapper->Uninitialize();
#ifdef _DEBUG
LONG cRef =
#endif
m_pWrapper->Release();
#ifdef _DEBUG
ft.Trace(VSSDBG_GEN, L"**** Final reference count for Wrapper = %ld - [%p]", cRef, this);
#endif
// disable for now
// BS_ASSERT(cRef == 0);
}
}
// default OnPrepareBackup method
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnPrepareBackup(IN IVssWriterComponents *pComponent)
{
UNREFERENCED_PARAMETER(pComponent);
return true;
}
// default OnIdentify method
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnIdentify(IN IVssCreateWriterMetadata *pMetadata)
{
UNREFERENCED_PARAMETER(pMetadata);
return true;
}
// default OnBackupComplete method
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnBackupComplete(IN IVssWriterComponents *pComponent)
{
UNREFERENCED_PARAMETER(pComponent);
return true;
}
// default OnBackupShutdown method
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnBackupShutdown(IN VSS_ID SnapshotSetId)
{
UNREFERENCED_PARAMETER(SnapshotSetId);
return true;
}
// default OnPreRestore method
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnPreRestore(IN IVssWriterComponents *pComponent)
{
UNREFERENCED_PARAMETER(pComponent);
return true;
}
// default OnPostRestore method
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnPostRestore(IN IVssWriterComponents *pComponent)
{
UNREFERENCED_PARAMETER(pComponent);
return true;
}
// default OnPostSnapshot method
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnPostSnapshot(IN IVssWriterComponents *pComponent)
{
UNREFERENCED_PARAMETER(pComponent);
return true;
}
// default OnBackOffIOOnVolume
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnBackOffIOOnVolume
(
IN VSS_PWSZ wszVolumeName,
IN VSS_ID snapshotId,
IN VSS_ID providerId
)
{
UNREFERENCED_PARAMETER(wszVolumeName);
UNREFERENCED_PARAMETER(snapshotId);
UNREFERENCED_PARAMETER(providerId);
return true;
}
// default OnContinueIOOnVolume
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnContinueIOOnVolume
(
IN VSS_PWSZ wszVolumeName,
IN VSS_ID snapshotId,
IN VSS_ID providerId
)
{
UNREFERENCED_PARAMETER(wszVolumeName);
UNREFERENCED_PARAMETER(snapshotId);
UNREFERENCED_PARAMETER(providerId);
return true;
}
// default OnVSSShutdown
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnVSSShutdown()
{
return true;
}
// default OnVSSApplicationStartup
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::OnVSSApplicationStartup()
{
return true;
}
// initialize the writer
// This function returns S_FALSE when the writer is inactive (setup or safe mode)
__declspec(dllexport)
HRESULT STDMETHODCALLTYPE CVssWriter::Initialize
(
IN VSS_ID WriterID,
IN LPCWSTR wszWriterName,
IN VSS_USAGE_TYPE ut,
IN VSS_SOURCE_TYPE st,
IN VSS_APPLICATION_LEVEL nLevel,
IN DWORD dwTimeoutFreeze,
IN VSS_ALTERNATE_WRITER_STATE aws,
IN bool bIOThrottlingOnly,
IN LPCWSTR wszReserved
)
{
UNREFERENCED_PARAMETER(wszReserved);
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::Initialize");
try
{
ft.Trace (VSSDBG_SHIM, L"Called CVssWriter::Initialize() with:");
ft.Trace (VSSDBG_SHIM, L" WriterId = " WSTR_GUID_FMT, GUID_PRINTF_ARG (WriterID));
ft.Trace (VSSDBG_SHIM, L" WriterName = %s", (NULL == wszWriterName) ? L"(NULL)" : wszWriterName);
ft.Trace (VSSDBG_SHIM, L" UsageType = %s", GetStringFromUsageType (ut));
ft.Trace (VSSDBG_SHIM, L" SourceType = %s", GetStringFromSourceType (st));
ft.Trace (VSSDBG_SHIM, L" AppLevel = %s", GetStringFromApplicationLevel (nLevel));
ft.Trace (VSSDBG_SHIM, L" FreezeTimeout = %d (ms)", dwTimeoutFreeze);
ft.Trace (VSSDBG_SHIM, L" AlternateWriterState = %s", GetStringFromAlternateWriterState(aws));
ft.Trace (VSSDBG_SHIM, L" IOThrottlingOnly = %s", bIOThrottlingOnly ? L"True" : L"False");
// The V2 parameters can only be set with default values
if (aws != VSS_AWS_NO_ALTERNATE_WRITER ||
bIOThrottlingOnly != false)
return E_INVALIDARG;
if (ut != VSS_UT_BOOTABLESYSTEMSTATE &&
ut != VSS_UT_SYSTEMSERVICE &&
ut != VSS_UT_USERDATA &&
ut != VSS_UT_OTHER)
return E_INVALIDARG;
// [aoltean] Previous comment was:
// return S_OK for now since there is a bug in the iis writer
// return S_OK;
if (st != VSS_ST_NONTRANSACTEDDB &&
st != VSS_ST_TRANSACTEDDB &&
st != VSS_ST_OTHER)
return E_INVALIDARG;
// [aoltean] Previous comment was:
// return S_OK for now since there is a bug in the IIS writer
// return S_OK;
CVssWriterImpl::CreateWriter(this, &m_pWrapper);
BS_ASSERT(m_pWrapper);
// call Initialize method on core instance
m_pWrapper->Initialize
(
WriterID,
wszWriterName,
ut,
st,
nLevel,
dwTimeoutFreeze
);
}
VSS_STANDARD_CATCH(ft)
return ft.hr;
}
// This function returns S_FALSE when the writer is inactive (setup or safe mode)
__declspec(dllexport)
HRESULT STDMETHODCALLTYPE CVssWriter::Subscribe
(
IN DWORD dwEventFlags
)
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::Subscribe");
try
{
ft.Trace (VSSDBG_GEN, L"**** Called CVssWriter::Subscribe(%p) with:", this);
ft.Trace (VSSDBG_GEN, L" dwEventFlags = 0x%08x ", dwEventFlags);
// Only the default parameter setting is supported in V1
if ( dwEventFlags != ( VSS_SM_BACKUP_EVENTS_FLAG | VSS_SM_RESTORE_EVENTS_FLAG ) )
return E_INVALIDARG;
if (m_pWrapper == NULL)
ft.Throw(VSSDBG_GEN, E_FAIL, L"CVssWriter class was not initialized.");
m_pWrapper->Subscribe();
}
VSS_STANDARD_CATCH(ft)
return ft.hr;
}
// This function returns S_FALSE when the writer is inactive (setup or safe mode)
__declspec(dllexport)
HRESULT STDMETHODCALLTYPE CVssWriter::Unsubscribe()
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::Unsubscribe");
try
{
if (m_pWrapper == NULL)
ft.Throw(VSSDBG_GEN, E_FAIL, L"CVssWriter class was not initialized.");
ft.Trace (VSSDBG_GEN, L"**** Called CVssWriter::Unsubscribe(%p):", this);
m_pWrapper->Unsubscribe();
}
VSS_STANDARD_CATCH(ft)
return ft.hr;
}
__declspec(dllexport)
HRESULT STDMETHODCALLTYPE CVssWriter::InstallAlternateWriter
(
IN VSS_ID writerId,
IN CLSID persistentWriterClassId
)
{
UNREFERENCED_PARAMETER(writerId);
UNREFERENCED_PARAMETER(persistentWriterClassId);
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::InstallAlternateWriter");
// Not supported in V1
ft.hr = E_NOTIMPL;
return ft.hr;
}
__declspec(dllexport)
LPCWSTR* STDMETHODCALLTYPE CVssWriter::GetCurrentVolumeArray() const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::GetCurrentVolumeArray");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return NULL;
else
return m_pWrapper->GetCurrentVolumeArray();
}
__declspec(dllexport)
UINT STDMETHODCALLTYPE CVssWriter::GetCurrentVolumeCount() const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::GetCurrentVolumeCount");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return 0;
else
return m_pWrapper->GetCurrentVolumeCount();
}
__declspec(dllexport)
HRESULT STDMETHODCALLTYPE CVssWriter::GetSnapshotDeviceName
(
IN LPCWSTR wszOriginalVolume,
OUT LPCWSTR* ppwszSnapshotDevice
) const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::GetSnapshotDeviceName");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return E_FAIL;
else
return m_pWrapper->GetSnapshotDeviceName(wszOriginalVolume, ppwszSnapshotDevice);
}
__declspec(dllexport)
VSS_ID STDMETHODCALLTYPE CVssWriter::GetCurrentSnapshotSetId() const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::GetCurrentSnapshotSetId");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return GUID_NULL;
else
return m_pWrapper->GetCurrentSnapshotSetId();
}
__declspec(dllexport)
LONG STDMETHODCALLTYPE CVssWriter::GetContext() const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::GetContext");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return 0;
else
return m_pWrapper->GetContext();
}
__declspec(dllexport)
VSS_APPLICATION_LEVEL STDMETHODCALLTYPE CVssWriter::GetCurrentLevel() const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::GetCurrentLevel");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return VSS_APP_AUTO;
else
return m_pWrapper->GetCurrentLevel();
}
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::IsPathAffected(IN LPCWSTR wszPath) const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::IsPathAffected");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return NULL;
else
return m_pWrapper->IsPathAffected(wszPath);
}
// determine if bootable state is backed up
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::IsBootableSystemStateBackedUp() const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::IsBootableSystemStateBackedUp");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return false;
else
return m_pWrapper->IsBootableSystemStateBackedUp();
}
// determine if bootable state is backed up
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::IsPartialFileSupportEnabled() const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::IsPartialFileSupportEnabled");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return false;
else
return m_pWrapper->IsPartialFileSupportEnabled();
}
// determine if the backup application is selecting components
__declspec(dllexport)
bool STDMETHODCALLTYPE CVssWriter::AreComponentsSelected() const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::AreComponentsSelected");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return false;
else
return m_pWrapper->AreComponentsSelected();
}
__declspec(dllexport)
VSS_BACKUP_TYPE STDMETHODCALLTYPE CVssWriter::GetBackupType() const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::GetBackupType");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return VSS_BT_UNDEFINED;
else
return m_pWrapper->GetBackupType();
}
__declspec(dllexport)
VSS_RESTORE_TYPE STDMETHODCALLTYPE CVssWriter::GetRestoreType() const
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::GetBackupType");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return VSS_RTYPE_UNDEFINED;
else
return m_pWrapper->GetRestoreType();
}
__declspec(dllexport)
HRESULT STDMETHODCALLTYPE CVssWriter::SetWriterFailure(IN HRESULT hrStatus)
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CVssWriter::SetWriterFailure");
BS_ASSERT(m_pWrapper);
if (m_pWrapper == NULL)
return VSS_BT_UNDEFINED;
else
return m_pWrapper->SetWriterFailure(hrStatus);
}
// create backup components
//
// Returns:
// S_OK if the operation is successful
// E_INVALIDARG if ppBackup is NULL
// E_ACCESSDENIED if the caller does not have backup privileges or
// is an administrator
__declspec(dllexport)
HRESULT STDAPICALLTYPE CreateVssBackupComponents(IVssBackupComponents **ppBackup)
{
CVssFunctionTracer ft(VSSDBG_XML, L"CreateVssBackupComponents");
try
{
if (ppBackup == NULL)
ft.Throw(VSSDBG_XML, E_INVALIDARG, L"NULL output pointer");
*ppBackup = NULL;
if (!IsProcessBackupOperator())
ft.Throw
(
VSSDBG_XML,
E_ACCESSDENIED,
L"The client process is not running under an administrator account or does not have backup privilege enabled"
);
CComObject<CVssBackupComponents> *pvbc;
CComObject<CVssBackupComponents>::CreateInstance(&pvbc);
pvbc->GetUnknown()->AddRef();
*ppBackup = (IVssBackupComponents *) pvbc;
}
VSS_STANDARD_CATCH(ft)
return ft.hr;
}
__declspec(dllexport)
HRESULT STDAPICALLTYPE CreateVssExamineWriterMetadata
(
IN BSTR bstrXML,
OUT IVssExamineWriterMetadata **ppMetadata
)
{
CVssFunctionTracer ft(VSSDBG_GEN, L"CreateVssExamineWriterMetadata");
CVssExamineWriterMetadata *pMetadata = NULL;
try
{
if (ppMetadata == NULL)
ft.Throw(VSSDBG_GEN, E_INVALIDARG, L"NULL output pointer");
*ppMetadata = NULL;
pMetadata = new CVssExamineWriterMetadata;
if (pMetadata == NULL)
ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Cannot allocate CVssExamineWriterMetadata");
if (!pMetadata->Initialize(bstrXML))
ft.Throw
(
VSSDBG_GEN,
VSS_E_INVALID_XML_DOCUMENT,
L"XML passed to CreateVssExamineWriterMetdata was invalid"
);
*ppMetadata = (IVssExamineWriterMetadata *) pMetadata;
pMetadata->AddRef();
}
VSS_STANDARD_CATCH(ft)
if (ft.HrFailed())
delete pMetadata;
return ft.hr;
}
// create a snapshot set description
//
// Returns:
// S_OK if it is successful
// E_OUTOFMEMORY if memory could not be allocated
__declspec(dllexport)
HRESULT STDAPICALLTYPE CreateVssSnapshotSetDescription
(
VSS_ID idSnapshotSet,
LONG lContext,
OUT IVssSnapshotSetDescription **ppSnapshotSet
)
{
CVssFunctionTracer ft(VSSDBG_XML, L"CreateVssSnapshotSsetDescription");
CVssSnapshotSetDescription *pSnapshotSetTemp = NULL;
try
{
CXMLDocument doc;
if (ppSnapshotSet == NULL)
ft.Throw(VSSDBG_XML, E_INVALIDARG, L"NULL output parameter.");
// intialize document with <root><schema></root>
doc.LoadFromXML(g_ComponentMetadataXML);
// find toplevel <root> element
if (!doc.FindElement(x_wszElementRoot, true))
ft.Throw(VSSDBG_XML, VSS_E_INVALID_XML_DOCUMENT, L"Missing root element");
// create BACKUP_COMPONENTS element under <root> element
CXMLNode nodeRoot(doc.GetCurrentNode(), doc.GetInterface());
CXMLNode nodeSnapshotSet = doc.CreateNode
(
x_wszElementSnapshotSetDescription,
NODE_ELEMENT
);
nodeSnapshotSet.SetAttribute(x_wszAttrSnapshotSetId, idSnapshotSet);
nodeSnapshotSet.SetAttribute(x_wszAttrContext, lContext);
nodeSnapshotSet.SetAttribute(x_wszAttrXmlns, x_wszValueXmlns);
CXMLNode nodeToplevel = nodeRoot.InsertNode(nodeSnapshotSet);
doc.SetToplevelNode(nodeSnapshotSet);
pSnapshotSetTemp = new CVssSnapshotSetDescription
(
doc.GetCurrentNode(),
doc.GetInterface()
);
if (pSnapshotSetTemp == NULL)
ft.Throw(VSSDBG_XML, E_OUTOFMEMORY, L"Can't allocate snapshot set description.");
pSnapshotSetTemp->Initialize(ft);
*ppSnapshotSet = (IVssSnapshotSetDescription *) pSnapshotSetTemp;
((IVssSnapshotSetDescription *) pSnapshotSetTemp)->AddRef();
pSnapshotSetTemp = NULL;
}
VSS_STANDARD_CATCH(ft)
delete pSnapshotSetTemp;
return ft.hr;
}
__declspec(dllexport)
HRESULT STDAPICALLTYPE LoadVssSnapshotSetDescription
(
IN LPCWSTR wszXML,
OUT IVssSnapshotSetDescription **ppSnapshotSet
)
{
CVssFunctionTracer ft(VSSDBG_XML, L"LoadVssSnapshotSetDescription");
try
{
CVssSnapshotSetDescription *pSnapshotSetDescription = new CVssSnapshotSetDescription;
if (pSnapshotSetDescription == NULL)
ft.Throw(VSSDBG_XML, E_OUTOFMEMORY, L"Cannot allocate snapshot set description.");
pSnapshotSetDescription->Initialize(ft);
pSnapshotSetDescription->LoadFromXML(wszXML);
((IVssSnapshotSetDescription *) pSnapshotSetDescription)->AddRef();
*ppSnapshotSet = (IVssSnapshotSetDescription *) pSnapshotSetDescription;
}
VSS_STANDARD_CATCH(ft)
return ft.hr;
}