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.
 
 
 
 
 
 

443 lines
13 KiB

/*
**++
**
** Copyright (c) 2002 Microsoft Corporation
**
**
** Module Name:
**
** writerconfig.cpp
**
**
** Abstract:
**
** defines classes that encapsulate the Test writer's configuration
**
** Author:
**
** Reuven Lax [reuvenl] 04-June-2002
**
**
**
** Revision History:
**
**--
*/
////////////////////////////////////////////////////////////////////////
// Includes
#include "stdafx.h"
#include "writerconfig.h"
#include "vs_xml.hxx"
#include "msxml2.h"
#include <string>
#include <sstream>
#include <algorithm>
////////////////////////////////////////////////////////////////////////
// Declarations
using Utility::checkReturn;
using Utility::AutoCS;
using std::wstring;
using std::wstringstream;
namespace XMLData {
// names of attributes and elements
wchar_t Name[] =L"name";
wchar_t Xmlns[] = L"xmlns";
wchar_t SchemaPointer[] = L"x-schema:#VssTestWriterConfig";
wchar_t RootStart[] = L"<root>";
wchar_t RootEnd[] = L"</root>\n";
wchar_t Root[] = L"root";
wchar_t TestWriter[] = L"TestWriter";
wchar_t Verbosity[] = L"verbosity";
wchar_t CheckExcludes[] = L"checkExcludes";
wchar_t CheckIncludes[] = L"checkIncludes";
wchar_t Path[] = L"path";
wchar_t Filespec[] = L"filespec";
wchar_t Recursive[] = L"recursive";
wchar_t AlternatePath[] = L"alternatePath";
wchar_t Usage[] = L"usage";
wchar_t RestoreMethod[] = L"RestoreMethod";
wchar_t Method[] = L"method";
wchar_t WriterRestore[] = L"writerRestore";
wchar_t Service[] = L"service";
wchar_t RebootRequired[] = L"rebootRequired";
wchar_t AlternateLocationMapping[] = L"AlternateLocationMapping";
wchar_t Component[] = L"Component";
wchar_t ComponentType[] = L"componentType";
wchar_t LogicalPath[] = L"logicalPath";
wchar_t Selectable[] = L"selectable";
wchar_t SelectableForRestore[] = L"selectableForRestore";
wchar_t ComponentName[] = L"componentName";
wchar_t ComponentFile[] = L"ComponentFile";
wchar_t Dependency[] = L"Dependency";
wchar_t WriterId[] = L"writerId";
wchar_t ExcludeFile[] = L"ExcludeFile";
wchar_t RestoreTarget[] = L"restoreTarget";
wchar_t NewTarget[] = L"NewTarget";
wchar_t FailEvent[] = L"FailEvent";
wchar_t WriterEvent[] = L"writerEvent";
wchar_t Retryable[] = L"retryable";
wchar_t NumFailures[] = L"numFailures";
// string containing the Test writer schema
#include "schema.h"
}
////////////////////////////////////////////////////////////////////////
// Implementation for the File struct
File::File(CXMLDocument node)
{
// read the attributes from the document and store in the structure
CComBSTR path;
if (!node.FindAttribute(XMLData::Path, &path))
missingAttribute(XMLData::Path);
CComBSTR filespec;
if (!node.FindAttribute(XMLData::Filespec, &filespec))
missingAttribute(XMLData::Filespec);
CComBSTR recursive;
if (!node.FindAttribute(XMLData::Recursive, &recursive))
missingAttribute(XMLData::Recursive);
m_path = (BSTR)path;
std::transform(m_path.begin(), m_path.end(), m_path.begin(), towupper);
m_filespec = (BSTR)filespec;
std::transform(m_filespec.begin(), m_filespec.end(), m_filespec.begin(), towupper);
// path and filespec should never be empty.
if (m_path.empty())
throw Utility::TestWriterException(L"File specification has empty path");
if (m_filespec.empty())
throw Utility::TestWriterException(L"File specification has empty filespec");
if (m_path[m_path.size() -1] != L'\\')
m_path += L'\\';
m_recursive = Utility::toBoolean(recursive);
}
wstring File::toString() const
{
wstringstream msg;
msg << L"Path: " << m_path << std::endl <<
L"Filespec: " << m_filespec << std::endl <<
L"Recursive: " << Utility::toString(m_recursive);
return msg.str();
}
////////////////////////////////////////////////////////////////////////
// Implementation for the TargetedFile struct
TargetedFile::TargetedFile(CXMLDocument node) : File(node)
{
// read the alternatePath attribute and store it
CComBSTR alternatePath;
if (!node.FindAttribute(XMLData::AlternatePath, &alternatePath))
return;
assert(alternatePath);
m_alternatePath = (BSTR)alternatePath;
std::transform(m_alternatePath.begin(), m_alternatePath.end(), m_alternatePath.begin(), towupper);
if (m_alternatePath.empty())
throw Utility::TestWriterException(L"File specification has empty alternate path");
if (m_alternatePath[m_alternatePath.size()-1] != L'\\')
m_alternatePath += L'\\';
}
wstring TargetedFile::toString() const
{
wstringstream msg;
msg << File::toString() << std::endl <<
L"AlternatePath: " << m_alternatePath;
return msg.str();
}
////////////////////////////////////////////////////////////////////////
// Implementation for the RestoreMethod struct
RestoreMethod::RestoreMethod(CXMLDocument node)
{
node.SetToplevel();
CComBSTR method, writerRestore, service, rebootRequired;
// read attributes and elements from document
if (!node.FindAttribute(XMLData::Method, &method))
missingAttribute(XMLData::Method);
if (!node.FindAttribute(XMLData::WriterRestore, &writerRestore))
missingAttribute(XMLData::WriterRestore);
node.FindAttribute(XMLData::Service, &service);
if(!node.FindAttribute(XMLData::RebootRequired, &rebootRequired))
missingAttribute(XMLData::RebootRequired);
if (node.FindElement(XMLData::AlternateLocationMapping, true))
m_alternateLocations = AlternateList(node);
m_method = Utility::toMethod(method);
m_writerRestore = Utility::toWriterRestore(writerRestore);
m_service = (service.Length() > 0) ? service : L"";
m_rebootRequired = Utility::toBoolean(rebootRequired);
}
wstring RestoreMethod::toString() const
{
wstringstream msg;
msg << L"method: " << Utility::toString(m_method) << std::endl <<
L"service: " << m_service << std::endl <<
L"writerRestore: " << Utility::toString(m_writerRestore) << std::endl <<
L"reboot: " << Utility::toString(m_rebootRequired);
return msg.str();
}
////////////////////////////////////////////////////////////////////////
// Implementation for the Dependency struct
Dependency::Dependency(CXMLDocument node)
{
node.SetToplevel();
CComBSTR logicalPath, componentName, writerId;
if(!node.FindAttribute(XMLData::WriterId, &writerId))
missingAttribute(XMLData::WriterId);
node.FindAttribute(XMLData::LogicalPath, &logicalPath);
if(!node.FindAttribute(XMLData::ComponentName, &componentName))
missingAttribute(XMLData::ComponentName);
HRESULT hr = ::UuidFromString(writerId, &m_writerId);
checkReturn(hr, L"CLSIDFromString");
m_logicalPath = (logicalPath.Length() > 0) ? logicalPath : L"";
m_componentName = componentName;
}
wstring Dependency::toString() const
{
wstringstream msg;
msg << L"WriterId: " << (wchar_t*)CComBSTR(m_writerId) << std::endl <<
L"Logical Path: " << m_logicalPath << std::endl <<
L"Component Name: " << m_componentName;
return msg.str();
}
////////////////////////////////////////////////////////////////////////
// Implementation for the Component struct
Component::Component(CXMLDocument node)
{
node.SetToplevel();
CComBSTR componentType, restoreTarget, logicalPath, name, selectable,
selectableForRestore;
// read attributes from document and store them
if (!node.FindAttribute(XMLData::ComponentType, &componentType))
missingAttribute(XMLData::ComponentType);
node.FindAttribute(XMLData::RestoreTarget, &restoreTarget);
node.FindAttribute(XMLData::LogicalPath, &logicalPath);
if (!node.FindAttribute(XMLData::ComponentName, &name))
missingAttribute(XMLData::ComponentName);
if (!node.FindAttribute(XMLData::Selectable, &selectable))
missingAttribute(XMLData::Selectable);
if (!node.FindAttribute(XMLData::SelectableForRestore, &selectableForRestore))
missingAttribute(XMLData::SelectableForRestore);
m_componentType = Utility::toComponentType(componentType);
m_restoreTarget = (restoreTarget.Length() > 0) ? Utility::toRestoreTarget(restoreTarget) : VSS_RT_UNDEFINED;
m_logicalPath = (logicalPath.Length() > 0) ? logicalPath : L"";
m_selectable = Utility::toBoolean(selectable);
m_selectableForRestore = Utility::toBoolean(selectableForRestore);
m_name = name;
if (m_name.empty())
throw Utility::TestWriterException(L"Component has empty name");
// read elements from document and store them
if (node.FindElement(XMLData::ComponentFile, true))
m_files = ComponentFileList(node);
node.ResetToDocument();
if (node.FindElement(XMLData::Dependency, true))
m_dependencies = DependencyList(node);
}
wstring ComponentBase::toString() const
{
wstringstream msg;
msg << L"Logical Path: " << m_logicalPath << std::endl <<
L"Name: " << m_name << std::endl;
return msg.str();
}
// comparison operations for writer components
bool operator==(const ComponentBase& left, const ComponentBase& right)
{
return (left.m_name == right.m_name) &&
(left.m_logicalPath == right.m_logicalPath);
}
bool operator!=(const ComponentBase& left, const ComponentBase& right)
{
return !(left == right);
}
bool operator==(const Component& left, const Component& right)
{
return ((ComponentBase&)left == (ComponentBase&)right) &&
(left.m_componentType == right.m_componentType) &&
(left.m_restoreTarget == right.m_restoreTarget) &&
(left.m_selectable == right.m_selectable) &&
(left.m_selectableForRestore == right.m_selectableForRestore) &&
(left.m_files == right.m_files) &&
(left.m_newTargets == right.m_newTargets);
}
bool operator!=(const Component& left, const Component& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////////////////
// Implementation for the WriterEvent struct
WriterEvent::WriterEvent(CXMLDocument node)
{
CComBSTR event;
if (!node.FindAttribute(XMLData::WriterEvent, &event))
missingAttribute(XMLData::WriterEvent);
CComBSTR retryable;
if (!node.FindAttribute(XMLData::Retryable, &retryable))
missingAttribute(XMLData::Retryable);
CComBSTR numFailures;
if (!node.FindAttribute(XMLData::NumFailures, &numFailures))
missingAttribute(XMLData::NumFailures);
m_writerEvent = Utility::toWriterEvent(event);
m_retryable = Utility::toBoolean(retryable);
m_numFailures = Utility::toLong(numFailures);
}
////////////////////////////////////////////////////////////////////////
// Implementation for the WriterConfiguration class
// load configuration from the XML file
void WriterConfiguration::loadFromXML(const wstring& xml)
{
AutoCS critical(m_section);
// load the document from the XML string
wstring xmlString = XMLData::RootStart;
xmlString += XMLData::Schema;
xmlString += xml;
xmlString += XMLData::RootEnd;
// load twice so we can do schema validation the second time
for (int x = 0; x < 2; x++) {
if (!m_doc.LoadFromXML(const_cast<wchar_t*> (xmlString.c_str())))
Utility::parseError(m_doc);
// --- skip to the part of the document we care about
if (!m_doc.FindElement(XMLData::Root, true))
missingElement(XMLData::Root);
if (!m_doc.FindElement(XMLData::TestWriter, true))
missingElement(XMLData::TestWriter);
// --- set the schema namespace
if (x == 0) {
CXMLNode testNode(m_doc.GetCurrentNode(), m_doc.GetInterface());
testNode.SetAttribute(XMLData::Xmlns, XMLData::SchemaPointer);
xmlString = m_doc.SaveAsXML();
}
}
m_doc.SetToplevel();
}
VSS_USAGE_TYPE WriterConfiguration::usage() const
{
assert(m_doc.GetLevel() == 0);
AutoCS critical(m_section);
Resetter reset(m_doc);
CComBSTR value;
if (!m_doc.FindAttribute(XMLData::Usage, &value))
missingAttribute(XMLData::Usage);
return Utility::toUsage(value);
}
Utility::Verbosity WriterConfiguration::verbosity() const
{
assert(m_doc.GetLevel() == 0);
AutoCS critical(m_section);
Resetter reset(m_doc);
CComBSTR value;
if (!m_doc.FindAttribute(XMLData::Verbosity, &value))
missingAttribute(XMLData::Verbosity);
return Utility::toVerbosity(value);
}
bool WriterConfiguration::checkExcludes() const
{
assert(m_doc.GetLevel() == 0);
AutoCS critical(m_section);
Resetter reset(m_doc);
CComBSTR value;
if (!m_doc.FindAttribute(XMLData::CheckExcludes, &value))
missingAttribute(XMLData::CheckExcludes);
return Utility::toBoolean(value);
}
bool WriterConfiguration::checkIncludes() const
{
assert(m_doc.GetLevel() == 0);
AutoCS critical(m_section);
Resetter reset(m_doc);
CComBSTR value;
if (!m_doc.FindAttribute(XMLData::CheckIncludes, &value))
missingAttribute(XMLData::CheckIncludes);
return Utility::toBoolean(value);
}
// get the writer's restore method
RestoreMethod WriterConfiguration::restoreMethod() const
{
assert(m_doc.GetLevel() == 0);
AutoCS critical(m_section);
Resetter reset(m_doc);
if (!m_doc.FindElement(XMLData::RestoreMethod, true))
missingElement(XMLData::RestoreMethod);
return RestoreMethod(m_doc);
}