Windows2003-3790/net/wlbs/xml/nlb_xmldocument.cpp
2020-09-30 16:53:55 +02:00

3226 lines
93 KiB
C++

/*
* Filename: NLB_XMLDocument.cpp
* Description:
* Author: shouse, 04.10.01
*/
#include <stdio.h>
#include <msxml3.tlh>
#include "NLB_XMLDocument.h"
#define CHECKHR(x) {hr = x; if (FAILED(hr)) {goto CleanUp;}}
#define CHECKALLOC(x) {if (!x) {hr = E_FAIL; goto CleanUp;}}
#define SAFERELEASE(p) {if (p) {(p)->Release(); p = NULL;}}
#define SAFEFREESTRING(p) {if (p) {SysFreeString(p); p = NULL;}}
#define NLB_XML_SCHEMA_NAME L"x-schema:MicrosoftNLB"
#define NLB_XML_SCHEMA_PATH L"MicrosoftNLB.xml"
#define NLB_XML_ELEMENT_NLB L"NLB"
#define NLB_XML_ELEMENT_CLUSTER L"Cluster"
#define NLB_XML_ELEMENT_PROPERTIES L"Properties"
#define NLB_XML_ELEMENT_HOSTS L"Hosts"
#define NLB_XML_ELEMENT_HOST L"Host"
#define NLB_XML_ELEMENT_PORTRULES L"PortRules"
#define NLB_XML_ELEMENT_PORTRULE L"PortRule"
#define NLB_XML_ELEMENT_PRIMARY_IPADDRESS L"PrimaryIPAddress"
#define NLB_XML_ELEMENT_SECONDARY_IPADDRESS L"SecondaryIPAddress"
#define NLB_XML_ELEMENT_IGMPMCAST_IPADDRESS L"IGMPMulticastIPAddress"
#define NLB_XML_ELEMENT_DEDICATED_IPADDRESS L"DedicatedIPAddress"
#define NLB_XML_ELEMENT_CONNECTION_IPADDRESS L"ConnectionIPAddress"
#define NLB_XML_ELEMENT_VIRTUAL_IPADDRESS L"VirtualIPAddress"
#define NLB_XML_ELEMENT_IPADDRESS L"IPAddress"
#define NLB_XML_ELEMENT_ADDRESS L"Address"
#define NLB_XML_ELEMENT_SUBNETMASK L"SubnetMask"
#define NLB_XML_ELEMENT_ADAPTER L"Adapter"
#define NLB_XML_ELEMENT_GUID L"GUID"
#define NLB_XML_ELEMENT_NAME L"Name"
#define NLB_XML_ELEMENT_DOMAINNAME L"DomainName"
#define NLB_XML_ELEMENT_HOSTNAME L"HostName"
#define NLB_XML_ELEMENT_NETWORKADDRESS L"NetworkAddress"
#define NLB_XML_ELEMENT_CLUSTER_MODE L"Mode"
#define NLB_XML_ELEMENT_REMOTE_CONTROL L"RemoteControl"
#define NLB_XML_ELEMENT_BDA L"BDA"
#define NLB_XML_ELEMENT_TEAMID L"TeamID"
#define NLB_XML_ELEMENT_HASHING L"Hashing"
#define NLB_XML_ELEMENT_FILTERING L"Filtering"
#define NLB_XML_ELEMENT_LOAD L"Load"
#define NLB_XML_ELEMENT_PRIORITY L"Priority"
#define NLB_XML_ELEMENT_NODE L"Node"
#define NLB_XML_ELEMENT_INITIAL_STATE L"InitialState"
#define NLB_XML_ATTRIBUTE_NAMESPACE L"xmlns"
#define NLB_XML_ATTRIBUTE_NAME L"Name"
#define NLB_XML_ATTRIBUTE_TEXT L"Text"
#define NLB_XML_ATTRIBUTE_ENABLED L"Enabled"
#define NLB_XML_ATTRIBUTE_MASTER L"Master"
#define NLB_XML_ATTRIBUTE_REVERSE L"Reverse"
#define NLB_XML_ATTRIBUTE_PASSWORD L"Password"
#define NLB_XML_ATTRIBUTE_HOSTID L"HostID"
#define NLB_XML_ATTRIBUTE_STATE L"State"
#define NLB_XML_ATTRIBUTE_START L"Start"
#define NLB_XML_ATTRIBUTE_END L"End"
#define NLB_XML_ATTRIBUTE_PROTOCOL L"Protocol"
#define NLB_XML_ATTRIBUTE_MODE L"Mode"
#define NLB_XML_ATTRIBUTE_AFFINITY L"Affinity"
#define NLB_XML_ATTRIBUTE_PRIORITY L"Priority"
#define NLB_XML_ATTRIBUTE_WEIGHT L"Weight"
#define NLB_XML_ATTRIBUTE_DEFAULT L"Default"
#define NLB_XML_ATTRIBUTE_STARTED L"Started"
#define NLB_XML_ATTRIBUTE_STOPPED L"Stopped"
#define NLB_XML_ATTRIBUTE_SUSPENDED L"Suspended"
#define NLB_XML_ATTRIBUTE_PERSIST_STARTED L"PersistStarted"
#define NLB_XML_ATTRIBUTE_PERSIST_STOPPED L"PersistStopped"
#define NLB_XML_ATTRIBUTE_PERSIST_SUSPENDED L"PersistSuspended"
#define NLB_XML_VALUE_NLB_SCHEMA L"x-schema:MicrosoftNLB.xml"
#define NLB_XML_VALUE_UNICAST L"Unicast"
#define NLB_XML_VALUE_MULTICAST L"Multicast"
#define NLB_XML_VALUE_IGMP L"IGMP"
#define NLB_XML_VALUE_STARTED L"Started"
#define NLB_XML_VALUE_STOPPED L"Stopped"
#define NLB_XML_VALUE_SUSPENDED L"Suspended"
#define NLB_XML_VALUE_TCP L"TCP"
#define NLB_XML_VALUE_UDP L"UDP"
#define NLB_XML_VALUE_BOTH L"Both"
#define NLB_XML_VALUE_ENABLED L"Enabled"
#define NLB_XML_VALUE_DISABLED L"Disabled"
#define NLB_XML_VALUE_DRAINING L"Draining"
#define NLB_XML_VALUE_SINGLE L"Single"
#define NLB_XML_VALUE_MULTIPLE L"Multiple"
#define NLB_XML_VALUE_NONE L"None"
#define NLB_XML_VALUE_CLASSC L"ClassC"
/*
* Method:
* Description:
* Author:
*/
NLB_XMLDocument::NLB_XMLDocument () {
pDoc = NULL;
pSchema = NULL;
bShowErrorPopups = false;
ZeroMemory(&ParseError, sizeof(NLB_XMLError));
CoInitialize(NULL);
}
/*
* Method:
* Description:
* Author:
*/
NLB_XMLDocument::NLB_XMLDocument (bool bSilent) {
pDoc = NULL;
pSchema = NULL;
bShowErrorPopups = !bSilent;
ZeroMemory(&ParseError, sizeof(NLB_XMLError));
CoInitialize(NULL);
}
/*
* Method:
* Description:
* Author:
*/
NLB_XMLDocument::~NLB_XMLDocument () {
CoUninitialize();
}
/*
* Method:
* Description:
* Author:
*/
void NLB_XMLDocument::GetParseError (NLB_XMLError & Error) {
Error = ParseError;
}
/*
* Method:
* Description:
* Author:
*/
void NLB_XMLDocument::SetParseError (HRESULT hrCode, PWSTR pwszReason) {
ParseError.code = hrCode;
lstrcpy(ParseError.wszReason, pwszReason);
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::LoadDocument (BSTR pBURL) {
MSXML2::IXMLDOMParseError * pXMLError = NULL;
VARIANT vURL;
VARIANT_BOOL vBool;
VARIANT vSchema;
HRESULT hr = S_OK;
CHECKHR(pDoc->put_async(VARIANT_FALSE));
VariantInit(&vURL);
vURL.vt = VT_BSTR;
V_BSTR(&vURL) = pBURL;
CHECKHR(CoCreateInstance(MSXML2::CLSID_XMLSchemaCache, NULL, CLSCTX_SERVER, MSXML2::IID_IXMLDOMSchemaCollection, (LPVOID*)(&pSchema)));
hr = pSchema->add(NLB_XML_SCHEMA_NAME, _variant_t(NLB_XML_SCHEMA_PATH));
if (hr != S_OK) {
PWCHAR pDescr = NULL;
IErrorInfo * pErrorInfo = NULL;
if (GetErrorInfo(0, &pErrorInfo) == S_OK) {
pErrorInfo->GetDescription(&pDescr);
ParseError.code = hr;
lstrcpy(ParseError.wszReason, pDescr);
}
goto CleanUp;
}
vSchema.vt = VT_DISPATCH;
vSchema.pdispVal = pSchema;
hr = pDoc->putref_schemas(vSchema);
if (hr != S_OK) {
PWCHAR pDescr = NULL;
IErrorInfo * pErrorInfo = NULL;
if (GetErrorInfo(0, &pErrorInfo) == S_OK) {
pErrorInfo->GetDescription(&pDescr);
ParseError.code = hr;
lstrcpy(ParseError.wszReason, pDescr);
}
goto CleanUp;
}
CHECKHR(pDoc->load(vURL, &vBool));
CheckDocumentLoad();
hr = pDoc->validate(&pXMLError);
if (hr != S_OK) {
CHECKHR(pXMLError->get_errorCode(&ParseError.code));
if (ParseError.code != 0) {
BSTR pBURL;
BSTR pBReason;
CHECKHR(pXMLError->get_line(&ParseError.line));
CHECKHR(pXMLError->get_linepos(&ParseError.character));
CHECKHR(pXMLError->get_URL(&pBURL));
lstrcpy(ParseError.wszURL, pBURL);
CHECKHR(pXMLError->get_reason(&pBReason));
lstrcpy(ParseError.wszReason, pBReason);
SAFEFREESTRING(pBURL);
SAFEFREESTRING(pBReason);
}
goto CleanUp;
}
CleanUp:
SAFERELEASE(pSchema);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::CheckDocumentLoad () {
MSXML2::IXMLDOMParseError * pXMLError = NULL;
HRESULT hr = S_OK;
CHECKHR(pDoc->get_parseError(&pXMLError));
CHECKHR(pXMLError->get_errorCode(&ParseError.code));
if (ParseError.code != 0) {
BSTR pBURL;
BSTR pBReason;
CHECKHR(pXMLError->get_line(&ParseError.line));
CHECKHR(pXMLError->get_linepos(&ParseError.character));
CHECKHR(pXMLError->get_URL(&pBURL));
lstrcpy(ParseError.wszURL, pBURL);
CHECKHR(pXMLError->get_reason(&pBReason));
lstrcpy(ParseError.wszReason, pBReason);
SAFEFREESTRING(pBURL);
SAFEFREESTRING(pBReason);
}
if (bShowErrorPopups) {
WCHAR reason[2048];
WCHAR details[2048];
if (ParseError.code != 0) {
wsprintf(reason, L"Error 0x%08x:\n\n%ls\n", ParseError.code, ParseError.wszReason);
if (ParseError.line > 0) {
wsprintf(details, L"Error on line %d, position %d in \"%ls\".\n", ParseError.line, ParseError.character, ParseError.wszURL);
lstrcat(reason, details);
}
::MessageBox(NULL, reason, L"NLB XML Document Error", MB_APPLMODAL | MB_ICONSTOP | MB_OK);
} else {
wsprintf(reason, L"XML Document successfully loaded.");
::MessageBox(NULL, reason, L"NLB XML Document Information", MB_APPLMODAL | MB_ICONINFORMATION | MB_OK);
}
}
CleanUp:
SAFERELEASE(pXMLError);
return ParseError.code;
}
/*
* Method:
* Description:
* Author:
*/
BSTR NLB_XMLDocument::AsciiToBSTR (const char * pszName) {
WCHAR wszString[MAX_PATH];
::MultiByteToWideChar(CP_ACP, 0, pszName, -1, wszString, MAX_PATH);
return SysAllocString(wszString);
}
/*
* Method:
* Description:
* Author:
*/
CHAR * NLB_XMLDocument::BSTRToAscii (const WCHAR * pwszName) {
CHAR szString[MAX_PATH];
::WideCharToMultiByte(CP_ACP, 0, pwszName, -1, szString, MAX_PATH, NULL, NULL);
return _strdup(szString);
}
/*
* Method:
* Description:
* Author:
*/
NLB_ClusterMode::NLB_ClusterModeType NLB_XMLDocument::StringToClusterMode (const PWCHAR pwszType) {
if (!lstrcmpi(pwszType, NLB_XML_VALUE_UNICAST)) {
return NLB_ClusterMode::Unicast;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_MULTICAST)) {
return NLB_ClusterMode::Multicast;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_IGMP)) {
return NLB_ClusterMode::IGMP;
}
return NLB_ClusterMode::Invalid;
}
/*
* Method:
* Description:
* Author:
*/
PWCHAR NLB_XMLDocument::ClusterModeToString (const NLB_ClusterMode::NLB_ClusterModeType Type) {
switch (Type) {
case NLB_ClusterMode::Unicast:
return L"Unicast";
case NLB_ClusterMode::Multicast:
return L"Multicast";
case NLB_ClusterMode::IGMP:
return L"IGMP";
}
return L"Invalid";
}
/*
* Method:
* Description:
* Author:
*/
NLB_HostState::NLB_HostStateType NLB_XMLDocument::StringToHostState (const PWCHAR pwszType) {
if (!lstrcmpi(pwszType, NLB_XML_VALUE_STARTED)) {
return NLB_HostState::Started;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_STOPPED)) {
return NLB_HostState::Stopped;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_SUSPENDED)) {
return NLB_HostState::Suspended;
}
return NLB_HostState::Invalid;
}
/*
* Method:
* Description:
* Author:
*/
PWCHAR NLB_XMLDocument::HostStateToString (const NLB_HostState::NLB_HostStateType Type) {
switch (Type) {
case NLB_HostState::Started:
return L"Started";
case NLB_HostState::Stopped:
return L"Stopped";
case NLB_HostState::Suspended:
return L"Suspended";
}
return L"Invalid";
}
/*
* Method:
* Description:
* Author:
*/
NLB_PortRuleProtocol::NLB_PortRuleProtocolType NLB_XMLDocument::StringToPortRuleProtocol (const PWCHAR pwszType) {
if (!lstrcmpi(pwszType, NLB_XML_VALUE_TCP)) {
return NLB_PortRuleProtocol::TCP;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_UDP)) {
return NLB_PortRuleProtocol::UDP;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_BOTH)) {
return NLB_PortRuleProtocol::Both;
}
return NLB_PortRuleProtocol::Invalid;
}
/*
* Method:
* Description:
* Author:
*/
PWCHAR NLB_XMLDocument::PortRuleProtocolToString (const NLB_PortRuleProtocol::NLB_PortRuleProtocolType Type) {
switch (Type) {
case NLB_PortRuleProtocol::TCP:
return L"TCP";
case NLB_PortRuleProtocol::UDP:
return L"UDP";
case NLB_PortRuleProtocol::Both:
return L"Both";
}
return L"Invalid";
}
/*
* Method:
* Description:
* Author:
*/
NLB_PortRuleFilteringMode::NLB_PortRuleFilteringModeType NLB_XMLDocument::StringToPortRuleFilteringMode (const PWCHAR pwszType) {
if (!lstrcmpi(pwszType, NLB_XML_VALUE_SINGLE)) {
return NLB_PortRuleFilteringMode::Single;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_MULTIPLE)) {
return NLB_PortRuleFilteringMode::Multiple;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_DISABLED)) {
return NLB_PortRuleFilteringMode::Disabled;
}
return NLB_PortRuleFilteringMode::Invalid;
}
/*
* Method:
* Description:
* Author:
*/
PWCHAR NLB_XMLDocument::PortRuleFilteringModeToString (const NLB_PortRuleFilteringMode::NLB_PortRuleFilteringModeType Type) {
switch (Type) {
case NLB_PortRuleFilteringMode::Single:
return L"Single";
case NLB_PortRuleFilteringMode::Multiple:
return L"Multiple";
case NLB_PortRuleFilteringMode::Disabled:
return L"Disabled";
}
return L"Invalid";
}
/*
* Method:
* Description:
* Author:
*/
NLB_PortRuleAffinity::NLB_PortRuleAffinityType NLB_XMLDocument::StringToPortRuleAffinity (const PWCHAR pwszType) {
if (!lstrcmpi(pwszType, NLB_XML_VALUE_NONE)) {
return NLB_PortRuleAffinity::None;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_SINGLE)) {
return NLB_PortRuleAffinity::Single;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_CLASSC)) {
return NLB_PortRuleAffinity::ClassC;
}
return NLB_PortRuleAffinity::Invalid;
}
/*
* Method:
* Description:
* Author:
*/
PWCHAR NLB_XMLDocument::PortRuleAffinityToString (const NLB_PortRuleAffinity::NLB_PortRuleAffinityType Type) {
switch (Type) {
case NLB_PortRuleAffinity::None:
return L"None";
case NLB_PortRuleAffinity::Single:
return L"Single";
case NLB_PortRuleAffinity::ClassC:
return L"ClassC";
}
return L"Invalid";
}
/*
* Method:
* Description:
* Author:
*/
NLB_PortRuleState::NLB_PortRuleStateType NLB_XMLDocument::StringToPortRuleState (const PWCHAR pwszType) {
if (!lstrcmpi(pwszType, NLB_XML_VALUE_ENABLED)) {
return NLB_PortRuleState::Enabled;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_DISABLED)) {
return NLB_PortRuleState::Disabled;
} else if (!lstrcmpi(pwszType, NLB_XML_VALUE_DRAINING)) {
return NLB_PortRuleState::Draining;
}
return NLB_PortRuleState::Invalid;
}
/*
* Method:
* Description:
* Author:
*/
PWCHAR NLB_XMLDocument::PortRuleStateToString (const NLB_PortRuleState::NLB_PortRuleStateType Type) {
switch (Type) {
case NLB_PortRuleState::Enabled:
return L"Enabled";
case NLB_PortRuleState::Disabled:
return L"Disabled";
case NLB_PortRuleState::Draining:
return L"Draining";
}
return L"Invalid";
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::GetIntegerAttribute (MSXML2::IXMLDOMNode * pNode, PWCHAR pAttribute, PULONG pValue) {
MSXML2::IXMLDOMElement * pElement = NULL;
HRESULT hr = S_OK;
VARIANT v;
BSTR BAttribute = NULL;
CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));
CHECKALLOC((BAttribute = SysAllocString(pAttribute)));
CHECKHR(pElement->getAttribute(BAttribute, &v));
if (hr == S_FALSE)
goto CleanUp;
if (v.vt != VT_BSTR) {
hr = E_FAIL;
goto CleanUp;
}
*pValue = _wtoi(V_BSTR(&v));
CleanUp:
SAFERELEASE(pElement);
SAFEFREESTRING(BAttribute);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::GetBooleanAttribute (MSXML2::IXMLDOMNode * pNode, PWCHAR pAttribute, bool * pValue) {
MSXML2::IXMLDOMElement * pElement = NULL;
HRESULT hr = S_OK;
VARIANT v;
ULONG value;
BSTR BAttribute = NULL;
CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));
CHECKALLOC((BAttribute = SysAllocString(pAttribute)));
CHECKHR(pElement->getAttribute(BAttribute, &v));
if (hr == S_FALSE)
goto CleanUp;
if (v.vt != VT_BSTR) {
hr = E_FAIL;
goto CleanUp;
}
value = _wtoi(V_BSTR(&v));
if (value)
*pValue = true;
else
*pValue = false;
CleanUp:
SAFERELEASE(pElement);
SAFEFREESTRING(BAttribute);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::GetStringAttribute (MSXML2::IXMLDOMNode * pNode, PWCHAR pAttribute, PWCHAR pValue, ULONG length) {
MSXML2::IXMLDOMElement * pElement = NULL;
HRESULT hr = S_OK;
VARIANT v;
BSTR BAttribute = NULL;
CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));
CHECKALLOC((BAttribute = SysAllocString(pAttribute)));
CHECKHR(pElement->getAttribute(BAttribute, &v));
if (hr == S_FALSE)
goto CleanUp;
if (v.vt != VT_BSTR) {
hr = E_FAIL;
goto CleanUp;
}
wcsncpy(pValue, V_BSTR(&v), length);
CleanUp:
SAFERELEASE(pElement);
SAFEFREESTRING(BAttribute);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::GetNodeValue (MSXML2::IXMLDOMNode * pNode, PWCHAR pValue, ULONG length) {
MSXML2::IXMLDOMNode * pChild = NULL;
VARIANT v;
HRESULT hr = S_OK;
CHECKHR(pNode->get_firstChild(&pChild));
if (!pChild) {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nodeValue(&v));
if (v.vt != VT_BSTR) {
hr = E_FAIL;
goto CleanUp;
}
wcsncpy(pValue, V_BSTR(&v), length);
CleanUp:
SAFERELEASE(pChild);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseFiltering (MSXML2::IXMLDOMNode * pNode, NLB_PortRule * pRule) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_MODE, wszString, MAX_PATH));
if (hr == S_OK)
pRule->SetFilteringMode(StringToPortRuleFilteringMode(wszString));
else if (hr == S_FALSE)
goto CleanUp;
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_AFFINITY, wszString, MAX_PATH));
if (hr == S_OK)
pRule->SetAffinity(StringToPortRuleAffinity(wszString));
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_LOAD)) {
CHECKHR(ParseLoadWeights(pChild, pRule));
} else if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_PRIORITY)) {
CHECKHR(ParsePriorities(pChild, pRule));
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParsePriorities (MSXML2::IXMLDOMNode * pNode, NLB_PortRule * pRule) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
ULONG value;
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_NODE)) {
CHECKHR(GetStringAttribute(pChild, NLB_XML_ATTRIBUTE_NAME, wszString, MAX_PATH));
if (hr == S_FALSE)
goto CleanUp;
CHECKHR(GetIntegerAttribute(pChild, NLB_XML_ATTRIBUTE_PRIORITY, &value));
if (hr == S_OK)
pRule->AddSingleHostFilteringPriority(wszString, value);
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseLoadWeights (MSXML2::IXMLDOMNode * pNode, NLB_PortRule * pRule) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
ULONG value;
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_NODE)) {
CHECKHR(GetStringAttribute(pChild, NLB_XML_ATTRIBUTE_NAME, wszString, MAX_PATH));
if (hr == S_FALSE)
goto CleanUp;
CHECKHR(GetIntegerAttribute(pChild, NLB_XML_ATTRIBUTE_WEIGHT, &value));
if (hr == S_OK)
pRule->AddMultipleHostFilteringLoadWeight(wszString, value);
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseBidirectionalAffinity (MSXML2::IXMLDOMNode * pNode, NLB_ClusterBDASupport * pBDA) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
BSTR BNodeName = NULL;
bool bValue;
HRESULT hr = S_OK;
CHECKHR(GetBooleanAttribute(pNode, NLB_XML_ATTRIBUTE_MASTER, &bValue));
if (hr == S_OK)
pBDA->SetMaster(bValue);
else if (hr == S_FALSE)
goto CleanUp;
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_TEAMID)) {
CHECKHR(GetNodeValue(pChild, wszString, MAX_PATH));
pBDA->SetTeamID(wszString);
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_HASHING)) {
CHECKHR(GetBooleanAttribute(pChild, NLB_XML_ATTRIBUTE_REVERSE, &bValue));
if (hr == S_OK)
pBDA->SetReverseHashing(bValue);
else if (hr == S_FALSE)
goto CleanUp;
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseRemoteControl (MSXML2::IXMLDOMNode * pNode, NLB_Cluster * pCluster) {
WCHAR wszString[MAX_PATH];
bool bValue;
HRESULT hr = S_OK;
CHECKHR(GetBooleanAttribute(pNode, NLB_XML_ATTRIBUTE_ENABLED, &bValue));
if (hr == S_OK)
pCluster->SetRemoteControlSupport(bValue);
else if (hr == S_FALSE)
goto CleanUp;
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_PASSWORD, wszString, MAX_PATH));
if (hr == S_OK)
pCluster->SetRemoteControlPassword(wszString);
CleanUp:
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseHostState (MSXML2::IXMLDOMNode * pNode, NLB_Host * pHost) {
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
BSTR BNodeName = NULL;
bool bValue;
HRESULT hr = S_OK;
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_DEFAULT, wszString, MAX_PATH));
if (hr == S_OK)
pHost->SetState(StringToHostState(wszString));
#if 0 /* Not supported yet. */
CHECKHR(GetBooleanAttribute(pNode, NLB_XML_ATTRIBUTE_PERSIST_STARTED, &bValue));
if (hr == S_OK)
pHost->SetStatePersistence(NLB_HostState::Started, bValue);
CHECKHR(GetBooleanAttribute(pNode, NLB_XML_ATTRIBUTE_PERSIST_STOPPED, &bValue));
if (hr == S_OK)
pHost->SetStatePersistence(NLB_HostState::Stopped, bValue);
#endif
CHECKHR(GetBooleanAttribute(pNode, NLB_XML_ATTRIBUTE_PERSIST_SUSPENDED, &bValue));
if (hr == S_OK)
pHost->SetStatePersistence(NLB_HostState::Suspended, bValue);
CleanUp:
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseAdapter (MSXML2::IXMLDOMNode * pNode, NLB_Adapter * pAdapter) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_GUID)) {
CHECKHR(GetNodeValue(pChild, wszString, MAX_PATH));
pAdapter->SetGUID(wszString);
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_NAME)) {
CHECKHR(GetNodeValue(pChild, wszString, MAX_PATH));
pAdapter->SetName(wszString);
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseIPAddress (MSXML2::IXMLDOMNode * pNode, NLB_IPAddress * pIPAddress) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_ADDRESS)) {
CHECKHR(GetNodeValue(pChild, wszString, MAX_PATH));
pIPAddress->SetIPAddress(wszString);
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_SUBNETMASK)) {
CHECKHR(GetNodeValue(pChild, wszString, MAX_PATH));
pIPAddress->SetSubnetMask(wszString);
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParsePortRule (MSXML2::IXMLDOMNode * pNode, NLB_PortRule * pRule) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
ULONG value1;
ULONG value2;
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_NAME, wszString, MAX_PATH));
if (hr == S_OK)
pRule->SetName(wszString);
else if (hr == S_FALSE)
goto CleanUp;
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_TEXT, wszString, MAX_PATH));
if (hr == S_OK)
pRule->SetLabel(wszString);
CHECKHR(GetIntegerAttribute(pNode, NLB_XML_ATTRIBUTE_START, &value1));
if (hr == S_FALSE)
goto CleanUp;
CHECKHR(GetIntegerAttribute(pNode, NLB_XML_ATTRIBUTE_END, &value2));
if (hr == S_FALSE)
goto CleanUp;
pRule->SetPortRange(value1, value2);
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_PROTOCOL, wszString, MAX_PATH));
if (hr == S_OK)
pRule->SetProtocol(StringToPortRuleProtocol(wszString));
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_STATE, wszString, MAX_PATH));
if (hr == S_OK)
pRule->SetState(StringToPortRuleState(wszString));
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_FILTERING)) {
CHECKHR(ParseFiltering(pChild, pRule));
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_VIRTUAL_IPADDRESS)) {
NLB_IPAddress IPAddress(NLB_IPAddress::Virtual);
CHECKHR(pChild->get_firstChild(&pNext));
if (pNext) {
SAFEFREESTRING(BNodeName);
CHECKHR(pNext->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_IPADDRESS)) {
CHECKHR(ParseIPAddress(pNext, &IPAddress));
pRule->SetVirtualIPAddress(IPAddress);
}
pNext->Release();
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseClusterPortRules (MSXML2::IXMLDOMNode * pNode, NLB_Cluster * pCluster) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_PORTRULE)) {
NLB_PortRule PortRule;
CHECKHR(ParsePortRule(pChild, &PortRule));
pCluster->AddPortRule(PortRule);
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseHost (MSXML2::IXMLDOMNode * pNode, NLB_Host * pHost) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
ULONG value;
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_NAME, wszString, MAX_PATH));
if (hr == S_OK)
pHost->SetName(wszString);
else if (hr == S_FALSE)
goto CleanUp;
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_TEXT, wszString, MAX_PATH));
if (hr == S_OK)
pHost->SetLabel(wszString);
CHECKHR(GetIntegerAttribute(pNode, NLB_XML_ATTRIBUTE_HOSTID, &value));
if (hr == S_OK)
pHost->SetHostID(value);
else if (hr == S_FALSE)
goto CleanUp;
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_HOSTNAME)) {
CHECKHR(GetNodeValue(pChild, wszString, MAX_PATH));
pHost->SetDNSHostname(wszString);
} else if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_INITIAL_STATE)) {
CHECKHR(ParseHostState(pChild, pHost));
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_DEDICATED_IPADDRESS)) {
NLB_IPAddress IPAddress(NLB_IPAddress::Dedicated);
NLB_Adapter Adapter;
CHECKHR(pChild->get_firstChild(&pNext));
while (pNext) {
MSXML2::IXMLDOMNode * pTemp = NULL;
SAFEFREESTRING(BNodeName);
CHECKHR(pNext->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_IPADDRESS)) {
CHECKHR(ParseIPAddress(pNext, &IPAddress));
pHost->SetDedicatedIPAddress(IPAddress);
} else if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_ADAPTER)) {
CHECKHR(ParseAdapter(pNext, &Adapter));
if (Adapter.GetName(wszString, MAX_PATH))
IPAddress.SetAdapterName(wszString);
else if (Adapter.GetGUID(wszString, MAX_PATH))
IPAddress.SetAdapterGUID(wszString);
pHost->SetDedicatedIPAddress(IPAddress);
}
CHECKHR(pNext->get_nextSibling(&pTemp));
pNext->Release();
pNext = pTemp;
pTemp = NULL;
SAFEFREESTRING(BNodeName);
}
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_CONNECTION_IPADDRESS)) {
NLB_IPAddress IPAddress(NLB_IPAddress::Connection);
CHECKHR(pChild->get_firstChild(&pNext));
if (pNext) {
SAFEFREESTRING(BNodeName);
CHECKHR(pNext->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_IPADDRESS)) {
CHECKHR(ParseIPAddress(pNext, &IPAddress));
pHost->SetConnectionIPAddress(IPAddress);
}
pNext->Release();
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_ADAPTER)) {
NLB_Adapter Adapter;
CHECKHR(ParseAdapter(pChild, &Adapter));
if (Adapter.GetName(wszString, MAX_PATH))
pHost->SetAdapterName(wszString);
else if (Adapter.GetGUID(wszString, MAX_PATH))
pHost->SetAdapterGUID(wszString);
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseClusterHosts (MSXML2::IXMLDOMNode * pNode, NLB_Cluster * pCluster) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_HOST)) {
NLB_Host Host;
CHECKHR(ParseHost(pChild, &Host));
pCluster->AddHost(Host);
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseClusterProperties (MSXML2::IXMLDOMNode * pNode, NLB_Cluster * pCluster) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_PRIMARY_IPADDRESS)) {
CHECKHR(pChild->get_firstChild(&pNext));
if (pNext) {
NLB_IPAddress IPAddress(NLB_IPAddress::Primary);
SAFEFREESTRING(BNodeName);
CHECKHR(pNext->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_IPADDRESS)) {
CHECKHR(ParseIPAddress(pNext, &IPAddress));
pCluster->SetPrimaryClusterIPAddress(IPAddress);
}
pNext->Release();
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_SECONDARY_IPADDRESS)) {
CHECKHR(pChild->get_firstChild(&pNext));
while (pNext) {
MSXML2::IXMLDOMNode * pTemp = NULL;
NLB_IPAddress IPAddress(NLB_IPAddress::Secondary);
SAFEFREESTRING(BNodeName);
CHECKHR(pNext->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_IPADDRESS)) {
CHECKHR(ParseIPAddress(pNext, &IPAddress));
pCluster->AddSecondaryClusterIPAddress(IPAddress);
}
CHECKHR(pNext->get_nextSibling(&pTemp));
pNext->Release();
pNext = pTemp;
pTemp = NULL;
SAFEFREESTRING(BNodeName);
}
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_IGMPMCAST_IPADDRESS)) {
CHECKHR(pChild->get_firstChild(&pNext));
if (pNext) {
NLB_IPAddress IPAddress(NLB_IPAddress::IGMP);
SAFEFREESTRING(BNodeName);
CHECKHR(pNext->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_IPADDRESS)) {
CHECKHR(ParseIPAddress(pNext, &IPAddress));
pCluster->SetIGMPMulticastIPAddress(IPAddress);
}
pNext->Release();
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_DOMAINNAME)) {
CHECKHR(GetNodeValue(pChild, wszString, MAX_PATH));
pCluster->SetDomainName(wszString);
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_NETWORKADDRESS)) {
CHECKHR(GetNodeValue(pChild, wszString, MAX_PATH));
pCluster->SetMACAddress(wszString);
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_CLUSTER_MODE)) {
CHECKHR(GetNodeValue(pChild, wszString, MAX_PATH));
pCluster->SetClusterMode(StringToClusterMode(wszString));
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_REMOTE_CONTROL)) {
CHECKHR(ParseRemoteControl(pChild, pCluster));
} else if (!lstrcmp(BNodeName, NLB_XML_ELEMENT_BDA)) {
NLB_ClusterBDASupport BDA;
CHECKHR(ParseBidirectionalAffinity(pChild, &BDA));
pCluster->SetBidirectionalAffinitySupport(BDA);
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::ParseCluster (MSXML2::IXMLDOMNode * pNode, NLB_Cluster * pCluster) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
WCHAR wszString[MAX_PATH];
BSTR BNodeName = NULL;
HRESULT hr = S_OK;
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_NAME, wszString, MAX_PATH));
if (hr == S_OK)
pCluster->SetName(wszString);
else if (hr == S_FALSE) {
hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NLB, NLB_ERROR_CLUSTER_NAME_MISSING);
SetParseError(hr, NLB_DESCR_CLUSTER_NAME_MISSING);
goto CleanUp;
}
CHECKHR(GetStringAttribute(pNode, NLB_XML_ATTRIBUTE_TEXT, wszString, MAX_PATH));
if (hr == S_OK)
pCluster->SetLabel(wszString);
CHECKHR(pNode->get_firstChild(&pChild));
while (pChild) {
CHECKHR(pChild->get_nodeName(&BNodeName));
CHECKALLOC(BNodeName);
if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_PROPERTIES)) {
CHECKHR(ParseClusterProperties(pChild, pCluster));
} else if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_HOSTS)) {
CHECKHR(ParseClusterHosts(pChild, pCluster));
} else if (!lstrcmpi(BNodeName, NLB_XML_ELEMENT_PORTRULES)) {
CHECKHR(ParseClusterPortRules(pChild, pCluster));
} else {
hr = E_FAIL;
goto CleanUp;
}
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
SAFEFREESTRING(BNodeName);
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
SAFEFREESTRING(BNodeName);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::Parse (const WCHAR * wszFileName, vector<NLB_Cluster> & Clusters) {
MSXML2::IXMLDOMNodeList * pList = NULL;
MSXML2::IXMLDOMNode * pNode = NULL;
BSTR BURL = NULL;
BSTR BTag = NULL;
LONG length;
LONG index;
HRESULT hr = S_OK;
CHECKHR(CoCreateInstance(MSXML2::CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, MSXML2::IID_IXMLDOMDocument2, (void**)&pDoc));
CHECKALLOC(pDoc);
CHECKALLOC((BURL = SysAllocString(wszFileName)));
CHECKALLOC((BTag = SysAllocString(NLB_XML_ELEMENT_CLUSTER)));
CHECKHR(LoadDocument(BURL));
if (ParseError.code != 0) {
hr = ParseError.code;
goto CleanUp;
}
CHECKHR(pDoc->getElementsByTagName(BTag, &pList));
CHECKALLOC(pList);
CHECKHR(pList->get_length(&length));
CHECKHR(pList->reset());
for (index = 0; index < length; index++) {
NLB_Cluster cluster;
CHECKHR(pList->get_item(index, &pNode));
CHECKALLOC(pNode);
CHECKHR(ParseCluster(pNode, &cluster));
Clusters.push_back(cluster);
SAFERELEASE(pNode);
}
CleanUp:
SAFERELEASE(pList);
SAFERELEASE(pNode);
SAFERELEASE(pDoc);
SAFEFREESTRING(BURL);
SAFEFREESTRING(BTag);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::Validate (const WCHAR * wszFileName) {
MSXML2::IXMLDOMNode * pNode = NULL;
WCHAR wszString[MAX_PATH];
BSTR BURL = NULL;
HRESULT hr = S_OK;
CHECKHR(CoCreateInstance(MSXML2::CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, MSXML2::IID_IXMLDOMDocument2, (void**)&pDoc));
CHECKALLOC(pDoc);
CHECKALLOC((BURL = SysAllocString(wszFileName)));
CHECKHR(LoadDocument(BURL));
if (ParseError.code != 0) {
hr = ParseError.code;
goto CleanUp;
}
CleanUp:
SAFERELEASE(pDoc);
SAFERELEASE(pNode);
SAFEFREESTRING(BURL);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
void NLB_XMLDocument::Print (vector<NLB_Cluster> Clusters) {
vector<NLB_Cluster>::iterator icluster;
NLB_IPAddress address;
WCHAR wszString[MAX_PATH];
ULONG value1;
ULONG value2;
bool bBool;
for (icluster = Clusters.begin(); icluster != Clusters.end(); icluster++) {
NLB_ClusterMode::NLB_ClusterModeType mode;
NLB_ClusterBDASupport bda;
vector<NLB_IPAddress>::iterator iaddress;
vector<NLB_IPAddress> addressList;
vector<NLB_Host>::iterator ihost;
vector<NLB_Host> hosts;
vector<NLB_PortRule>::iterator irule;
vector<NLB_PortRule> rules;
NLB_Cluster * pCluster = icluster;
if (pCluster->GetName(wszString, MAX_PATH))
printf("\nCluster name: %ls ", wszString);
if (pCluster->GetLabel(wszString, MAX_PATH))
printf("(%ls)", wszString);
printf("\n");
if (pCluster->GetPrimaryClusterIPAddress(address)) {
if (address.GetIPAddress(wszString, MAX_PATH))
printf(" Primary Cluster IP Address: %ls\n", wszString);
if (address.GetSubnetMask(wszString, MAX_PATH))
printf(" Subnet Mask: %ls\n", wszString);
}
if (pCluster->GetClusterMode(mode)) {
switch (mode) {
case NLB_ClusterMode::Unicast:
printf(" Cluster Mode: Unicast\n");
break;
case NLB_ClusterMode::Multicast:
printf(" Cluster Mode: Multicast\n");
break;
case NLB_ClusterMode::IGMP:
printf(" Cluster Mode: IGMP\n");
break;
default:
break;
}
}
if (pCluster->GetIGMPMulticastIPAddress(address)) {
if (address.GetIPAddress(wszString, MAX_PATH))
printf(" IGMP Multicast IP Address: %ls\n", wszString);
}
if (pCluster->GetDomainName(wszString, MAX_PATH))
printf(" Domain Name: %ls\n", wszString);
if (pCluster->GetMACAddress(wszString, MAX_PATH))
printf(" Network Address: %ls\n", wszString);
if (pCluster->GetRemoteControlSupport(bBool)) {
switch (bBool) {
case true:
printf(" Remote Control: Enabled ");
if (pCluster->GetRemoteControlPassword(wszString, MAX_PATH))
printf("(Password=%ls)", wszString);
break;
case false:
printf(" Remote Control: Disabled");
break;
}
printf("\n");
}
if (pCluster->GetSecondaryClusterIPAddressList(&addressList)) {
printf(" Secondary Cluster IP Addresses\n");
for (iaddress = addressList.begin(); iaddress != addressList.end(); iaddress++) {
NLB_IPAddress * paddress = iaddress;
if (paddress->GetIPAddress(wszString, MAX_PATH))
printf(" IP Address: %ls\n", wszString);
if (paddress->GetSubnetMask(wszString, MAX_PATH))
printf(" Subnet Mask: %ls\n", wszString);
}
}
if (pCluster->GetBidirectionalAffinitySupport(bda)) {
printf(" Bidirectional Affinity\n");
if (bda.GetTeamID(wszString, MAX_PATH))
printf(" TeamID: %ls\n", wszString);
if (bda.GetMaster(bBool))
printf(" Master: %ls\n", (bBool) ? L"Yes" : L"No");
if (bda.GetReverseHashing(bBool))
printf(" Reverse hashing: %ls\n", (bBool) ? L"Yes" : L"No");
}
pCluster->GetHostList(&hosts);
for (ihost = hosts.begin(); ihost != hosts.end(); ihost++) {
NLB_HostState::NLB_HostStateType state;
NLB_Host * pHost = ihost;
if (pHost->GetName(wszString, MAX_PATH))
printf("\n Host name: %ls ", wszString);
if (pHost->GetLabel(wszString, MAX_PATH))
printf("(%ls)", wszString);
printf("\n");
if (pHost->GetAdapterName(wszString, MAX_PATH))
printf(" Adapter Name: %ls\n", wszString);
else if (pHost->GetAdapterGUID(wszString, MAX_PATH))
printf(" Adapter GUID: %ls\n", wszString);
if (pHost->GetHostID(value1))
printf(" Host ID: %d\n", value1);
if (pHost->GetState(state)) {
switch (state) {
case NLB_HostState::Started:
printf(" State: Started\n");
break;
case NLB_HostState::Stopped:
printf(" State: Stopped\n");
break;
case NLB_HostState::Suspended:
printf(" State: Suspended\n");
break;
default:
break;
}
printf(" Persisted States: ");
if (pHost->GetStatePersistence(NLB_HostState::Suspended, bBool) && bBool)
printf("Suspended\n");
else
printf("None\n");
}
if (pHost->GetDNSHostname(wszString, MAX_PATH))
printf(" Hostname: %ls\n", wszString);
if (pHost->GetDedicatedIPAddress(address)) {
if (address.GetIPAddress(wszString, MAX_PATH))
printf(" Dedicated Cluster IP Address: %ls\n", wszString);
if (address.GetSubnetMask(wszString, MAX_PATH))
printf(" Subnet Mask: %ls\n", wszString);
if (address.GetAdapterName(wszString, MAX_PATH))
printf(" Adapter Name: %ls\n", wszString);
else if (address.GetAdapterGUID(wszString, MAX_PATH))
printf(" Adapter GUID: %ls\n", wszString);
}
if (pHost->GetConnectionIPAddress(address)) {
if (address.GetIPAddress(wszString, MAX_PATH))
printf(" Connection Cluster IP Address: %ls\n", wszString);
if (address.GetSubnetMask(wszString, MAX_PATH))
printf(" Subnet Mask: %ls\n", wszString);
}
}
pCluster->GetPortRuleList(&rules);
for (irule = rules.begin(); irule != rules.end(); irule++) {
NLB_PortRuleState::NLB_PortRuleStateType state;
NLB_PortRuleProtocol::NLB_PortRuleProtocolType protocol;
NLB_PortRuleFilteringMode::NLB_PortRuleFilteringModeType mode;
NLB_PortRuleAffinity::NLB_PortRuleAffinityType affinity;
NLB_PortRule * pRule = irule;
if (pRule->GetName(wszString, MAX_PATH))
printf("\n Port rule name: %ls ", wszString);
if (pRule->GetLabel(wszString, MAX_PATH))
printf("(%ls)", wszString);
printf("\n");
if (pRule->GetState(state)) {
switch (state) {
case NLB_PortRuleState::Enabled:
printf(" State: Enabled\n");
break;
case NLB_PortRuleState::Disabled:
printf(" State: Disabled\n");
break;
case NLB_PortRuleState::Draining:
printf(" State: Draining\n");
break;
default:
break;
}
}
if (pRule->GetVirtualIPAddress(address)) {
if (address.GetIPAddress(wszString, MAX_PATH))
printf(" Virtual IP Address: %ls\n", wszString);
}
if (pRule->GetPortRange(value1, value2)) {
printf(" Start: %d\n", value1);
printf(" End: %d\n", value2);
}
if (pRule->GetProtocol(protocol)) {
switch (protocol) {
case NLB_PortRuleProtocol::TCP:
printf(" Protocol: TCP\n");
break;
case NLB_PortRuleProtocol::UDP:
printf(" Protocol: UDP\n");
break;
case NLB_PortRuleProtocol::Both:
printf(" Protocol: Both\n");
break;
default:
break;
}
}
if (pRule->GetFilteringMode(mode)) {
switch (mode) {
case NLB_PortRuleFilteringMode::Single:
printf(" Filtering Mode: Single\n");
for (ihost = hosts.begin(); ihost != hosts.end(); ihost++) {
NLB_Host * pHost = ihost;
if (pHost->GetName(wszString, MAX_PATH)) {
if (pRule->GetSingleHostFilteringPriority(wszString, value1))
printf(" Priority: %-2u (%ls)\n", value1, wszString);
}
}
break;
case NLB_PortRuleFilteringMode::Multiple:
printf(" Filtering Mode: Multiple\n");
if (pRule->GetAffinity(affinity)) {
switch (affinity) {
case NLB_PortRuleAffinity::None:
printf(" Affinity: None\n");
break;
case NLB_PortRuleAffinity::Single:
printf(" Affinity: Single\n");
break;
case NLB_PortRuleAffinity::ClassC:
printf(" Affinity: Class C\n");
break;
default:
break;
}
}
for (ihost = hosts.begin(); ihost != hosts.end(); ihost++) {
NLB_Host * pHost = ihost;
if (pHost->GetName(wszString, MAX_PATH)) {
if (pRule->GetMultipleHostFilteringLoadWeight(wszString, value1))
printf(" Load Weight: %-3u (%ls)\n", value1, wszString);
}
}
break;
case NLB_PortRuleFilteringMode::Disabled:
printf(" Filtering Mode: Disabled\n");
break;
default:
break;
}
}
}
}
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SetIntegerAttribute (MSXML2::IXMLDOMNode * pNode, PWCHAR pAttribute, ULONG value) {
MSXML2::IXMLDOMElement * pElement = NULL;
VARIANT v;
HRESULT hr = S_OK;
BSTR BAttribute = NULL;
CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));
CHECKALLOC((BAttribute = SysAllocString(pAttribute)));
v.vt = VT_I4;
V_I4(&v) = value;
CHECKHR(pElement->setAttribute(BAttribute, v));
CleanUp:
SAFERELEASE(pElement);
SAFEFREESTRING(BAttribute);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SetBooleanAttribute (MSXML2::IXMLDOMNode * pNode, PWCHAR pAttribute, bool value) {
MSXML2::IXMLDOMElement * pElement = NULL;
VARIANT v;
HRESULT hr = S_OK;
BSTR BAttribute = NULL;
CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));
CHECKALLOC((BAttribute = SysAllocString(pAttribute)));
v.vt = VT_BOOL;
V_BOOL(&v) = value;
CHECKHR(pElement->setAttribute(BAttribute, v));
CleanUp:
SAFERELEASE(pElement);
SAFEFREESTRING(BAttribute);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SetStringAttribute (MSXML2::IXMLDOMNode * pNode, PWCHAR pAttribute, PWCHAR pValue) {
MSXML2::IXMLDOMElement * pElement = NULL;
VARIANT v;
HRESULT hr = S_OK;
BSTR BAttribute = NULL;
BSTR BValue = NULL;
CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));
CHECKALLOC((BAttribute = SysAllocString(pAttribute)));
CHECKALLOC((BValue = SysAllocString(pValue)));
v.vt = VT_BSTR;
V_BSTR(&v) = BValue;
CHECKHR(pElement->setAttribute(BAttribute, v));
CleanUp:
SAFERELEASE(pElement);
SAFEFREESTRING(BAttribute);
SAFEFREESTRING(BValue);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SetNodeValue (MSXML2::IXMLDOMNode * pNode, PWCHAR pValue) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNewChild = NULL;
BSTR BValue = NULL;
VARIANT RefNode;
VARIANT v;
HRESULT hr = S_OK;
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_TEXT, NULL)));
CHECKALLOC((BValue = SysAllocString(pValue)));
v.vt = VT_BSTR;
V_BSTR(&v) = BValue;
CHECKHR(pChild->put_nodeValue(v));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
SAFEFREESTRING(BValue);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
MSXML2::IXMLDOMNode * NLB_XMLDocument::CreateNode (MSXML2::IXMLDOMDocument * pDoc, int type, PWCHAR pName) {
MSXML2::IXMLDOMNode * pNode;
BSTR BName = NULL;
VARIANT vtype;
HRESULT hr = S_OK;
if (pName)
CHECKALLOC((BName = SysAllocString(pName)));
vtype.vt = VT_I4;
V_I4(&vtype) = (int)type;
CHECKHR(pDoc->createNode(vtype, BName, NULL, &pNode));
SAFEFREESTRING(BName);
return pNode;
CleanUp:
SAFEFREESTRING(BName);
return NULL;
}
/*
* Method:
* Description:
* Author:
*/
MSXML2::IXMLDOMNode * NLB_XMLDocument::CreateNode (MSXML2::IXMLDOMDocument * pDoc, int type, PWCHAR pName, PWCHAR pValue) {
MSXML2::IXMLDOMNode * pNode;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, type, pName)));
CHECKHR(SetNodeValue(pNode, pValue));
return pNode;
CleanUp:
return NULL;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveRemoteControl (MSXML2::IXMLDOMNode * pRoot, NLB_Cluster * pCluster) {
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
WCHAR wszString[MAX_PATH];
bool bBool;
VARIANT RefNode;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_REMOTE_CONTROL)));
if (pCluster->GetRemoteControlSupport(bBool))
CHECKHR(SetBooleanAttribute(pNode, NLB_XML_ATTRIBUTE_ENABLED, bBool));
if (pCluster->GetRemoteControlPassword(wszString, MAX_PATH))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_PASSWORD, wszString));
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveHostState (MSXML2::IXMLDOMNode * pRoot, NLB_Host * pHost) {
NLB_HostState::NLB_HostStateType State;
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
bool bBool;
VARIANT RefNode;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_INITIAL_STATE)));
if (pHost->GetState(State))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_DEFAULT, HostStateToString(State)));
#if 0 /* Not supported yet. */
if (pHost->GetStatePersistence(NLB_HostState::Started, bBool))
CHECKHR(SetBooleanAttribute(pNode, NLB_XML_ATTRIBUTE_PERSIST_STARTED, bBool));
if (pHost->GetStatePersistence(NLB_HostState::Stopped, bBool))
CHECKHR(SetBooleanAttribute(pNode, NLB_XML_ATTRIBUTE_PERSIST_STOPPED, bBool));
#endif
if (pHost->GetStatePersistence(NLB_HostState::Suspended, bBool))
CHECKHR(SetBooleanAttribute(pNode, NLB_XML_ATTRIBUTE_PERSIST_SUSPENDED, bBool));
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveBidirectionalAffinity (MSXML2::IXMLDOMNode * pRoot, NLB_ClusterBDASupport * pBDA) {
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNewChild = NULL;
WCHAR wszString[MAX_PATH];
bool bBool;
VARIANT RefNode;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_BDA)));
if (pBDA->GetMaster(bBool))
CHECKHR(SetBooleanAttribute(pNode, NLB_XML_ATTRIBUTE_MASTER, bBool));
if (pBDA->GetTeamID(wszString, MAX_PATH)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_TEAMID, wszString)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pBDA->GetReverseHashing(bBool)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_HASHING)));
CHECKHR(SetBooleanAttribute(pChild, NLB_XML_ATTRIBUTE_REVERSE, bBool));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveAdapter (MSXML2::IXMLDOMNode * pRoot, NLB_Adapter * pAdapter) {
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNewChild = NULL;
WCHAR wszString[MAX_PATH];
VARIANT RefNode;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_ADAPTER)));
if (pAdapter->GetName(wszString, MAX_PATH)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_NAME, wszString)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
} else if (pAdapter->GetGUID(wszString, MAX_PATH)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_GUID, wszString)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveIPAddress (MSXML2::IXMLDOMNode * pRoot, NLB_IPAddress * pAddress) {
NLB_IPAddress::NLB_IPAddressType Type;
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNewChild = NULL;
WCHAR wszString[MAX_PATH];
VARIANT RefNode;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_IPADDRESS)));
if (pAddress->GetIPAddress(wszString, MAX_PATH)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_ADDRESS, wszString)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pAddress->GetSubnetMask(wszString, MAX_PATH)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_SUBNETMASK, wszString)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveLoadWeights (MSXML2::IXMLDOMNode * pRoot, NLB_PortRule * pRule) {
vector<NLB_PortRuleLoadWeight>::iterator iLoadWeight;
vector<NLB_PortRuleLoadWeight> LoadWeightList;
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNewChild = NULL;
WCHAR wszString[MAX_PATH];
ULONG value;
VARIANT RefNode;
HRESULT hr = S_OK;
if (pRule->GetMultipleHostFilteringLoadWeightList(&LoadWeightList)) {
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_LOAD)));
for (iLoadWeight = LoadWeightList.begin(); iLoadWeight != LoadWeightList.end(); iLoadWeight++) {
NLB_PortRuleLoadWeight * pLoadWeight = iLoadWeight;
if (!pLoadWeight->IsValid())
continue;
if (!pLoadWeight->GetHost(wszString, MAX_PATH))
continue;
if (!pLoadWeight->GetWeight(value))
continue;
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_NODE)));
CHECKHR(SetStringAttribute(pChild, NLB_XML_ATTRIBUTE_NAME, wszString));
CHECKHR(SetIntegerAttribute(pChild, NLB_XML_ATTRIBUTE_WEIGHT, value));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
}
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SavePriorities (MSXML2::IXMLDOMNode * pRoot, NLB_PortRule * pRule) {
vector<NLB_PortRulePriority>::iterator iPriority;
vector<NLB_PortRulePriority> PriorityList;
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNewChild = NULL;
WCHAR wszString[MAX_PATH];
ULONG value;
VARIANT RefNode;
HRESULT hr = S_OK;
if (pRule->GetSingleHostFilteringPriorityList(&PriorityList)) {
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_PRIORITY)));
for (iPriority = PriorityList.begin(); iPriority != PriorityList.end(); iPriority++) {
NLB_PortRulePriority * pPriority = iPriority;
if (!pPriority->IsValid())
continue;
if (!pPriority->GetHost(wszString, MAX_PATH))
continue;
if (!pPriority->GetPriority(value))
continue;
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_NODE)));
CHECKHR(SetStringAttribute(pChild, NLB_XML_ATTRIBUTE_NAME, wszString));
CHECKHR(SetIntegerAttribute(pChild, NLB_XML_ATTRIBUTE_PRIORITY, value));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
}
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveFiltering (MSXML2::IXMLDOMNode * pRoot, NLB_PortRule * pRule) {
NLB_PortRuleFilteringMode::NLB_PortRuleFilteringModeType Mode;
NLB_PortRuleAffinity::NLB_PortRuleAffinityType Affinity;
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
VARIANT RefNode;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_FILTERING)));
if (pRule->GetFilteringMode(Mode))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_MODE, PortRuleFilteringModeToString(Mode)));
switch (Mode) {
case NLB_PortRuleFilteringMode::Single:
CHECKHR(SavePriorities(pNode, pRule));
break;
case NLB_PortRuleFilteringMode::Multiple:
if (pRule->GetAffinity(Affinity))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_AFFINITY, PortRuleAffinityToString(Affinity)));
CHECKHR(SaveLoadWeights(pNode, pRule));
break;
case NLB_PortRuleFilteringMode::Disabled:
break;
}
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SavePortRule (MSXML2::IXMLDOMNode * pRoot, NLB_PortRule * pRule) {
NLB_PortRuleFilteringMode::NLB_PortRuleFilteringModeType Mode;
NLB_PortRuleProtocol::NLB_PortRuleProtocolType Protocol;
NLB_PortRuleState::NLB_PortRuleStateType State;
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNewChild = NULL;
WCHAR wszString[MAX_PATH];
ULONG value1;
ULONG value2;
VARIANT RefNode;
NLB_IPAddress Address;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_PORTRULE)));
if (pRule->GetName(wszString, MAX_PATH))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_NAME, wszString));
if (pRule->GetLabel(wszString, MAX_PATH))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_TEXT, wszString));
if (pRule->GetPortRange(value1, value2)) {
CHECKHR(SetIntegerAttribute(pNode, NLB_XML_ATTRIBUTE_START, value1));
CHECKHR(SetIntegerAttribute(pNode, NLB_XML_ATTRIBUTE_END, value2));
}
if (pRule->GetProtocol(Protocol))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_PROTOCOL, PortRuleProtocolToString(Protocol)));
if (pRule->GetState(State))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_STATE, PortRuleStateToString(State)));
if (pRule->GetVirtualIPAddress(Address)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_VIRTUAL_IPADDRESS)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
CHECKHR(SaveIPAddress(pChild, &Address));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pRule->GetFilteringMode(Mode))
CHECKHR(SaveFiltering(pNode, pRule));
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveHost (MSXML2::IXMLDOMNode * pRoot, NLB_Host * pHost) {
NLB_HostState::NLB_HostStateType State;
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNewChild = NULL;
WCHAR wszString[MAX_PATH];
bool bBool;
ULONG value;
VARIANT RefNode;
NLB_IPAddress Address;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_HOST)));
if (pHost->GetName(wszString, MAX_PATH))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_NAME, wszString));
if (pHost->GetHostID(value))
CHECKHR(SetIntegerAttribute(pNode, NLB_XML_ATTRIBUTE_HOSTID, value));
if (pHost->GetLabel(wszString, MAX_PATH))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_TEXT, wszString));
if (pHost->GetDNSHostname(wszString, MAX_PATH)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_HOSTNAME, wszString)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pHost->GetAdapterName(wszString, MAX_PATH)) {
NLB_Adapter Adapter;
Adapter.SetName(wszString);
CHECKHR(SaveAdapter(pNode, &Adapter));
} else if (pHost->GetAdapterGUID(wszString, MAX_PATH)) {
NLB_Adapter Adapter;
Adapter.SetGUID(wszString);
CHECKHR(SaveAdapter(pNode, &Adapter));
}
if (pHost->GetState(State))
CHECKHR(SaveHostState(pNode, pHost));
if (pHost->GetDedicatedIPAddress(Address)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_DEDICATED_IPADDRESS)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
CHECKHR(SaveIPAddress(pChild, &Address));
if (Address.GetAdapterName(wszString, MAX_PATH)) {
NLB_Adapter Adapter;
Adapter.SetName(wszString);
CHECKHR(SaveAdapter(pChild, &Adapter));
} else if (Address.GetAdapterGUID(wszString, MAX_PATH)) {
NLB_Adapter Adapter;
Adapter.SetGUID(wszString);
CHECKHR(SaveAdapter(pChild, &Adapter));
}
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pHost->GetConnectionIPAddress(Address)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_CONNECTION_IPADDRESS)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
CHECKHR(SaveIPAddress(pChild, &Address));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveClusterPortRules (MSXML2::IXMLDOMNode * pRoot, NLB_Cluster * pCluster) {
vector<NLB_PortRule>::iterator iRule;
vector<NLB_PortRule> RuleList;
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
VARIANT RefNode;
HRESULT hr = S_OK;
if (pCluster->GetPortRuleList(&RuleList)) {
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_PORTRULES)));
for (iRule = RuleList.begin(); iRule != RuleList.end(); iRule++) {
NLB_PortRule * pRule = iRule;
if (pRule->IsValid())
CHECKHR(SavePortRule(pNode, pRule));
}
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
}
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveClusterHosts (MSXML2::IXMLDOMNode * pRoot, NLB_Cluster * pCluster) {
vector<NLB_Host>::iterator iHost;
vector<NLB_Host> HostList;
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
VARIANT RefNode;
HRESULT hr = S_OK;
if (pCluster->GetHostList(&HostList)) {
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_HOSTS)));
for (iHost = HostList.begin(); iHost != HostList.end(); iHost++) {
NLB_Host * pHost = iHost;
if (pHost->IsValid())
CHECKHR(SaveHost(pNode, pHost));
}
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
}
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveClusterProperties (MSXML2::IXMLDOMNode * pRoot, NLB_Cluster * pCluster) {
NLB_ClusterMode::NLB_ClusterModeType Mode;
vector<NLB_IPAddress>::iterator iAddress;
vector<NLB_IPAddress> AddressList;
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNewChild = NULL;
WCHAR wszString[MAX_PATH];
bool bBool;
VARIANT RefNode;
NLB_IPAddress Address;
NLB_ClusterBDASupport BDA;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_PROPERTIES)));
if (pCluster->GetPrimaryClusterIPAddress(Address)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_PRIMARY_IPADDRESS)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
CHECKHR(SaveIPAddress(pChild, &Address));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pCluster->GetSecondaryClusterIPAddressList(&AddressList)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_SECONDARY_IPADDRESS)));
for (iAddress = AddressList.begin(); iAddress != AddressList.end(); iAddress++) {
NLB_IPAddress * pAddress = iAddress;
if (pAddress->IsValid())
CHECKHR(SaveIPAddress(pChild, pAddress));
}
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pCluster->GetIGMPMulticastIPAddress(Address)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_IGMPMCAST_IPADDRESS)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
CHECKHR(SaveIPAddress(pChild, &Address));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pCluster->GetDomainName(wszString, MAX_PATH)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_DOMAINNAME, wszString)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pCluster->GetClusterMode(Mode)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_CLUSTER_MODE, ClusterModeToString(Mode))));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pCluster->GetMACAddress(wszString, MAX_PATH)) {
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_NETWORKADDRESS, wszString)));
RefNode.vt = VT_EMPTY;
CHECKHR(pNode->insertBefore(pChild, RefNode, &pNewChild));
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
}
if (pCluster->GetRemoteControlSupport(bBool))
CHECKHR(SaveRemoteControl(pNode, pCluster));
if (pCluster->GetBidirectionalAffinitySupport(BDA))
CHECKHR(SaveBidirectionalAffinity(pNode, &BDA));
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::SaveCluster (MSXML2::IXMLDOMNode * pRoot, NLB_Cluster * pCluster) {
MSXML2::IXMLDOMNode * pNode = NULL;
MSXML2::IXMLDOMNode * pNewNode = NULL;
WCHAR wszString[MAX_PATH];
VARIANT RefNode;
HRESULT hr = S_OK;
CHECKALLOC((pNode = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_CLUSTER)));
if (pCluster->GetName(wszString, MAX_PATH))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_NAME, wszString));
if (pCluster->GetLabel(wszString, MAX_PATH))
CHECKHR(SetStringAttribute(pNode, NLB_XML_ATTRIBUTE_TEXT, wszString));
CHECKHR(SaveClusterProperties(pNode, pCluster));
CHECKHR(SaveClusterHosts(pNode, pCluster));
CHECKHR(SaveClusterPortRules(pNode, pCluster));
RefNode.vt = VT_EMPTY;
CHECKHR(pRoot->insertBefore(pNode, RefNode, &pNewNode));
CleanUp:
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::Save (const WCHAR * wszFileName, vector<NLB_Cluster> Clusters) {
vector<NLB_Cluster>::iterator iCluster;
MSXML2::IXMLDOMNode * pRoot = NULL;
BSTR BURL = NULL;
VARIANT vName;
HRESULT hr = S_OK;
CHECKHR(CoCreateInstance(MSXML2::CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, MSXML2::IID_IXMLDOMDocument2, (void**)&pDoc));
CHECKALLOC(pDoc);
CHECKALLOC((pRoot = CreateNode(pDoc, MSXML2::NODE_ELEMENT, NLB_XML_ELEMENT_NLB)));
CHECKHR(SetStringAttribute(pRoot, NLB_XML_ATTRIBUTE_NAMESPACE, NLB_XML_VALUE_NLB_SCHEMA));
for (iCluster = Clusters.begin(); iCluster != Clusters.end(); iCluster++) {
vector<NLB_Cluster>::iterator iOtherCluster;
NLB_Cluster * pCluster = iCluster;
bool bWrite = true;
if (pCluster->IsValid()) {
for (iOtherCluster = iCluster + 1; iOtherCluster != Clusters.end(); iOtherCluster++) {
NLB_Cluster * pOtherCluster = iOtherCluster;
WCHAR wszOtherName[MAX_PATH];
WCHAR wszName[MAX_PATH];
if (!pCluster->GetName(wszName, MAX_PATH))
bWrite = false;
if (!pOtherCluster->GetName(wszOtherName, MAX_PATH))
bWrite = false;
if (!lstrcmpi(wszName, wszOtherName))
bWrite = false;
}
if (bWrite)
CHECKHR(SaveCluster(pRoot, pCluster));
}
}
CHECKHR(pDoc->appendChild(pRoot, NULL));
CHECKHR(BeautifyDocument(pRoot, 0));
CHECKALLOC((BURL = SysAllocString(wszFileName)));
vName.vt = VT_BSTR;
V_BSTR(&vName) = BURL;
CHECKHR(pDoc->save(vName));
CleanUp:
SAFERELEASE(pDoc);
SAFERELEASE(pRoot);
SAFEFREESTRING(BURL);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::InsertFormatting (PWCHAR Text, MSXML2::IXMLDOMNode * pUnder, MSXML2::IXMLDOMNode * pBefore) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNewChild = NULL;
BSTR BValue = NULL;
VARIANT RefNode;
VARIANT value;
HRESULT hr = S_OK;
CHECKALLOC((pChild = CreateNode(pDoc, MSXML2::NODE_TEXT, NULL)));
CHECKALLOC((BValue = SysAllocString(Text)));
value.vt = VT_BSTR;
V_BSTR(&value) = BValue;
CHECKHR(pChild->put_nodeValue(value));
RefNode.vt = VT_UNKNOWN;
V_UNKNOWN(&RefNode) = pBefore;
CHECKHR(pUnder->insertBefore(pChild, RefNode, &pNewChild));
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNewChild);
return hr;
}
/*
* Method:
* Description:
* Author:
*/
HRESULT NLB_XMLDocument::BeautifyDocument (MSXML2::IXMLDOMNode * pNode, ULONG depth) {
MSXML2::IXMLDOMNode * pChild = NULL;
MSXML2::IXMLDOMNode * pNext = NULL;
MSXML2::DOMNodeType NodeType;
WCHAR wszInsertText[MAX_PATH];
WCHAR wszInsertTextAtEnd[MAX_PATH];
bool bLastNodeWasText = false;
bool bThisNodeIsText = false;
int i;
HRESULT hr = S_OK;
wcscpy(wszInsertText, L"\n");
for (i = 0; i < depth; i++)
wcscat(wszInsertText, L" ");
wcscpy(wszInsertTextAtEnd, wszInsertText);
wcscat(wszInsertText, L" ");
depth += 1;
CHECKHR(pNode->get_firstChild(&pChild));
if (pChild) {
while (pChild) {
CHECKHR(pChild->get_nodeType(&NodeType));
bThisNodeIsText = (NodeType == MSXML2::NODE_TEXT);
if (!bLastNodeWasText && !bThisNodeIsText)
CHECKHR(InsertFormatting(wszInsertText, pNode, pChild));
bLastNodeWasText = bThisNodeIsText;
CHECKHR(BeautifyDocument(pChild, depth));
CHECKHR(pChild->get_nextSibling(&pNext));
pChild->Release();
pChild = pNext;
pNext = NULL;
}
if (!bLastNodeWasText)
CHECKHR(InsertFormatting(wszInsertTextAtEnd, pNode, NULL));
}
CleanUp:
SAFERELEASE(pChild);
SAFERELEASE(pNext);
return hr;
}