WindowsXP-SP1/enduser/windows.com/iuengine/iuxml.cpp
2020-09-30 16:53:49 +02:00

5228 lines
155 KiB
C++

//=======================================================================
//
// Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
//
// File: iuxml.cpp
//
// Description:
//
// Implementation for the CIUXml class
//
//=======================================================================
#include "iuengine.h"
#include "iuxml.h"
#include <iucommon.h>
#include <fileutil.h>
#include <StringUtil.h>
#include <shlwapi.h>
#include <wininet.h>
#include "schemakeys.h"
#include "schemamisc.h"
#include "v3applog.h"
#define QuitIfNull(p) {if (NULL == p) {hr = E_INVALIDARG; LOG_ErrorMsg(hr); return hr;}}
#define QuitIfFail(x) {hr = x; if (FAILED(hr)) goto CleanUp;}
#define ReturnIfFail(x) {hr = x; if (FAILED(hr)) {LOG_ErrorMsg(hr); return hr;}}
#define SkipIfFail(x) {hr = x; if (FAILED(hr)) {hr = S_FALSE; continue;}}
const TCHAR IDENT_IUSCHEMA[] = _T("IUSchema");
const TCHAR IDENT_IUSCHEMA_SYSTEMSPEC[] = _T("SystemSpecSchema");
const TCHAR IDENT_IUSCHEMA_ITEMS[] = _T("ResultSchema");
const WCHAR CORP_PLATFORM_DIR_NT4[] = L"x86WinNT4";
const WCHAR CORP_PLATFORM_DIR_NT5[] = L"x86win2k";
const WCHAR CORP_PLATFORM_DIR_W98[] = L"x86Win98";
const WCHAR CORP_PLATFORM_DIR_W95[] = L"x86Win95";
const WCHAR CORP_PLATFORM_DIR_WINME[] = L"x86WinME";
const WCHAR CORP_PLATFORM_DIR_X86WHI[] = L"x86WinXP";
const WCHAR CORP_PLATFROM_DIR_IA64WHI[] = L"ia64WinXP";
// Initial length of the node array "m_ppNodeArray"
const DWORD MAX_NODES = 16;
// Initial length of the node array "m_ppNodeListArray"
const DWORD MAX_NODELISTS = 16;
// Bitmap of existence of all possible system info classes
const DWORD COMPUTERSYSTEM = 0x00000001;
const DWORD REGKEYS = 0x00000010;
const DWORD PLATFORM = 0x00000100;
const DWORD LOCALE = 0x00001000;
const DWORD DEVICES = 0x00010000;
// The following are constants used for V3 history migration:
//
// Log line types
#define LOG_V2 "V2" // line format for items migrated from V2
#define LOG_V3CAT "V3CAT" // V3 Beta format (version 1)
#define LOG_V3_2 "V3_2" // V3 log line format (version 2)
#define LOG_PSS "PSS" // Entry for PSS
// LOG_V2 format
// V2|DATE|TIME|LOGSTRING|
//
// LOG_V3CAT format
// V3CAT|PUID|OPERATION|TITLE|VERSION|DATESTRING|TIMESTRING|RECTYPE|RESULT|ERRORCODE|ERRORSTRING|
//
// LOG_V3_2 format
// V3_2|PUID|OPERATION|TITLE|VERSION|TIMESTAMP|RECTYPE|RESULT|ERRORCODE|ERRORSTRING|
//
// LOG_PSS format
// PSS|PUID|OPERATION|TITLE|VERSION|TIMESTAMP|RECTYPE|RESULT|ERRORCODE|ERRORSTRING|
//
// operation type
#define LOG_INSTALL "INSTALL"
// result
#define LOG_SUCCESS "SUCCESS"
#define LOG_FAIL "FAIL"
#define LOG_STARTED "STARTED" // started but reboot was required: exclusive items only
const WCHAR C_V3_CLIENTINFO[] = L"WU_V3";
/////////////////////////////////////////////////////////////////////////////
// CIUXml
/////////////////////////////////////////////////////////////////////////////
// Constructor
//
/////////////////////////////////////////////////////////////////////////////
CIUXml::CIUXml()
: m_dwSizeNodeArray(MAX_NODES),
m_dwSizeNodeListArray(MAX_NODELISTS),
m_ppNodeArray(NULL),
m_ppNodeListArray(NULL)
{
m_hHeap = GetProcessHeap();
}
/////////////////////////////////////////////////////////////////////////////
// Destructor
//
/////////////////////////////////////////////////////////////////////////////
CIUXml::~CIUXml()
{
DWORD dwIndex;
if (NULL != m_ppNodeArray)
{
for (dwIndex = 0; dwIndex < m_dwSizeNodeArray; dwIndex++)
{
SafeReleaseNULL(m_ppNodeArray[dwIndex]);
}
HeapFree(m_hHeap, 0, m_ppNodeArray);
m_ppNodeArray = NULL;
}
if (NULL != m_ppNodeListArray)
{
for (dwIndex = 0; dwIndex < m_dwSizeNodeListArray; dwIndex++)
{
SafeReleaseNULL(m_ppNodeListArray[dwIndex]);
}
HeapFree(m_hHeap, 0, m_ppNodeListArray);
m_ppNodeListArray = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////
// SafeCloseHandleNode()
//
// User can explicitly can this function to release a node for reuse when
// writing a xml doc.
/////////////////////////////////////////////////////////////////////////////
void CIUXml::SafeCloseHandleNode(HANDLE_NODE& hNode)
{
if (HANDLE_NODE_INVALID != hNode)
{
SafeReleaseNULL(m_ppNodeArray[hNode]);
hNode = HANDLE_NODE_INVALID;
}
}
/////////////////////////////////////////////////////////////////////////////
// SafeFindCloseHandle()
//
// User can explicitly can this function to release a nodelist for reuse when
// reading a xml doc.
/////////////////////////////////////////////////////////////////////////////
void CIUXml::SafeFindCloseHandle(HANDLE_NODELIST& hNodeList)
{
if (HANDLE_NODELIST_INVALID != hNodeList)
{
SafeReleaseNULL(m_ppNodeListArray[hNodeList]);
hNodeList = HANDLE_NODELIST_INVALID;
}
}
/////////////////////////////////////////////////////////////////////////////
// InitNodeArray()
//
// Allocate or re-allocate memory for the node array "m_ppNodeArray"
/////////////////////////////////////////////////////////////////////////////
HRESULT CIUXml::InitNodeArray(BOOL fRealloc /*= FALSE*/)
{
if (fRealloc) // re-allocation
{
IXMLDOMNode** ppNodeArrayTemp = (IXMLDOMNode**)HeapReAlloc(m_hHeap,
HEAP_ZERO_MEMORY,
m_ppNodeArray,
m_dwSizeNodeArray * sizeof(IXMLDOMNode*));
if (NULL == ppNodeArrayTemp)
{
return E_OUTOFMEMORY;
}
else
{
m_ppNodeArray = ppNodeArrayTemp;
}
}
else // initial allocation
{
m_ppNodeArray = (IXMLDOMNode**)HeapAlloc(m_hHeap,
HEAP_ZERO_MEMORY,
m_dwSizeNodeArray * sizeof(IXMLDOMNode*));
if (NULL == m_ppNodeArray)
{
return E_OUTOFMEMORY;
}
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// InitNodeListArray()
//
// Allocate or re-allocate memory for the nodelist array "m_ppNodeListArray"
/////////////////////////////////////////////////////////////////////////////
HRESULT CIUXml::InitNodeListArray(BOOL fRealloc /*= FALSE*/)
{
if (fRealloc) // re-allocation
{
IXMLDOMNodeList** ppNodeListArrayTemp = (IXMLDOMNodeList**)HeapReAlloc(m_hHeap,
HEAP_ZERO_MEMORY,
m_ppNodeListArray,
m_dwSizeNodeListArray * sizeof(IXMLDOMNodeList*));
if (NULL == ppNodeListArrayTemp)
{
return E_OUTOFMEMORY;
}
else
{
m_ppNodeListArray = ppNodeListArrayTemp;
}
}
else // initial allocation
{
m_ppNodeListArray = (IXMLDOMNodeList**)HeapAlloc(m_hHeap,
HEAP_ZERO_MEMORY,
m_dwSizeNodeListArray * sizeof(IXMLDOMNodeList*));
if (NULL == m_ppNodeListArray)
{
return E_OUTOFMEMORY;
}
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// GetNodeHandle()
//
// Look for the first un-used node from the "m_ppNodeArray" array,
// including the memory allocation, if needed.
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODE CIUXml::GetNodeHandle()
{
HRESULT hr;
DWORD dwIndex;
//
// allocate memory for "m_ppNodeArray" array if this is the first time using it
//
if (NULL == m_ppNodeArray)
{
QuitIfFail(InitNodeArray());
return 0; // return the first element of the array
}
//
// find the next node to use, or, if any node was used but closed, reuse it
//
for (dwIndex = 0; dwIndex < m_dwSizeNodeArray; dwIndex++)
{
if (NULL == m_ppNodeArray[dwIndex])
{
return dwIndex;
}
}
//
// all pre-allocated nodes are used up, so re-allocate longer array
//
m_dwSizeNodeArray += m_dwSizeNodeArray; // double the size
QuitIfFail(InitNodeArray(TRUE)); // re-allocation
return dwIndex;
CleanUp:
return HANDLE_NODE_INVALID;
}
/////////////////////////////////////////////////////////////////////////////
// GetNodeListHandle()
//
// Look for the first un-used nodelist from the "m_ppNodeListArray" array,
// including the memory allocation, if needed.
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CIUXml::GetNodeListHandle()
{
HRESULT hr;
DWORD dwIndex;
//
// allocate memory for "m_ppNodeListArray" array if this is the first time using it
//
if (NULL == m_ppNodeListArray)
{
QuitIfFail(InitNodeListArray());
return 0; // return the first element of the array
}
//
// find the next nodelist to use, or, if any nodelist was used but closed, reuse it
//
for (dwIndex = 0; dwIndex < m_dwSizeNodeListArray; dwIndex++)
{
if (NULL == m_ppNodeListArray[dwIndex])
{
return dwIndex;
}
}
//
// all pre-allocated nodelists are used up, so re-allocate longer array
//
m_dwSizeNodeListArray += m_dwSizeNodeListArray; // double the size
QuitIfFail(InitNodeListArray(TRUE)); // re-allocation
return dwIndex;
CleanUp:
return HANDLE_NODELIST_INVALID;
}
/////////////////////////////////////////////////////////////////////////////
// GetDOMNodebyHandle()
//
// Retrieve the xml node with the given index of m_ppNodeArray
/////////////////////////////////////////////////////////////////////////////
IXMLDOMNode* CIUXml::GetDOMNodebyHandle(HANDLE_NODE hNode)
{
if (NULL != m_ppNodeArray && HANDLE_NODE_INVALID != hNode)
{
return m_ppNodeArray[hNode];
}
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// FindFirstDOMNode()
//
// Retrieve the first xml node with the given tag name under the given parent node
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CIUXml::FindFirstDOMNode(IXMLDOMNode* pParentNode, BSTR bstrName, IXMLDOMNode** ppNode)
{
USES_IU_CONVERSION;
HRESULT hr = S_OK;
if (NULL == pParentNode)
{
hr = E_INVALIDARG;
return HANDLE_NODELIST_INVALID;
}
DWORD dwIndex;
dwIndex = GetNodeListHandle();
if (HANDLE_NODELIST_INVALID != dwIndex)
{
LONG lLength;
QuitIfFail(pParentNode->selectNodes(bstrName, &m_ppNodeListArray[dwIndex]));
if (NULL == m_ppNodeListArray[dwIndex])
{
goto CleanUp;
}
QuitIfFail(m_ppNodeListArray[dwIndex]->get_length(&lLength));
if (lLength <= 0)
{
goto CleanUp;
}
QuitIfFail(m_ppNodeListArray[dwIndex]->nextNode(ppNode));
if (NULL == *ppNode)
{
goto CleanUp;
}
return dwIndex;
}
CleanUp:
*ppNode = NULL;
return HANDLE_NODELIST_INVALID;
}
/////////////////////////////////////////////////////////////////////////////
// FindFirstDOMNode()
//
// Retrieve the handle of first xml node with the given tag name under the given parent node
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CIUXml::FindFirstDOMNode(IXMLDOMNode* pParentNode, BSTR bstrName, HANDLE_NODE* phNode)
{
USES_IU_CONVERSION;
HRESULT hr = S_OK;
if (NULL == pParentNode)
{
hr = E_INVALIDARG;
return HANDLE_NODELIST_INVALID;
}
DWORD dwIndex1, dwIndex2;
dwIndex1 = GetNodeListHandle();
if (HANDLE_NODELIST_INVALID != dwIndex1)
{
LONG lLength;
QuitIfFail(pParentNode->selectNodes(bstrName, &m_ppNodeListArray[dwIndex1]));
if (NULL == m_ppNodeListArray[dwIndex1])
{
goto CleanUp;
}
QuitIfFail(m_ppNodeListArray[dwIndex1]->get_length(&lLength));
if (lLength <= 0)
{
goto CleanUp;
}
dwIndex2 = GetNodeHandle();
if (HANDLE_NODE_INVALID != dwIndex2)
{
QuitIfFail(m_ppNodeListArray[dwIndex1]->nextNode(&m_ppNodeArray[dwIndex2]));
if (NULL == m_ppNodeArray[dwIndex2])
{
goto CleanUp;
}
*phNode = dwIndex2;
return dwIndex1;
}
}
CleanUp:
*phNode = HANDLE_NODE_INVALID;
return HANDLE_NODELIST_INVALID;
}
/////////////////////////////////////////////////////////////////////////////
// FindFirstDOMNode()
//
// Retrieve the first xml node with the given tag name in the given xml doc
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CIUXml::FindFirstDOMNode(IXMLDOMDocument* pDoc, BSTR bstrName, IXMLDOMNode** ppNode)
{
USES_IU_CONVERSION;
HRESULT hr = S_OK;
if (NULL == pDoc)
{
hr = E_INVALIDARG;
return HANDLE_NODELIST_INVALID;
}
DWORD dwIndex;
IXMLDOMNode *pParentNode = NULL;
dwIndex = GetNodeListHandle();
if (HANDLE_NODELIST_INVALID != dwIndex)
{
LONG lLength;
QuitIfFail(pDoc->QueryInterface(IID_IXMLDOMNode, (void**)&pParentNode));
QuitIfFail(pParentNode->selectNodes(bstrName, &m_ppNodeListArray[dwIndex]));
if (NULL == m_ppNodeListArray[dwIndex])
{
goto CleanUp;
}
QuitIfFail(m_ppNodeListArray[dwIndex]->get_length(&lLength));
if (lLength <= 0)
{
goto CleanUp;
}
QuitIfFail(m_ppNodeListArray[dwIndex]->nextNode(ppNode));
if (NULL == *ppNode)
{
goto CleanUp;
}
SafeReleaseNULL(pParentNode);
return dwIndex;
}
CleanUp:
*ppNode = NULL;
SafeReleaseNULL(pParentNode);
return HANDLE_NODELIST_INVALID;
}
/////////////////////////////////////////////////////////////////////////////
// FindFirstDOMNode()
//
// Retrieve the handle of first xml node with the given tag name in the given xml doc
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CIUXml::FindFirstDOMNode(IXMLDOMDocument* pDoc, BSTR bstrName, HANDLE_NODE* phNode)
{
USES_IU_CONVERSION;
HRESULT hr = S_OK;
if (NULL == pDoc)
{
hr = E_INVALIDARG;
return HANDLE_NODELIST_INVALID;
}
DWORD dwIndex1, dwIndex2;
IXMLDOMNode *pParentNode = NULL;
dwIndex1 = GetNodeListHandle();
if (HANDLE_NODELIST_INVALID != dwIndex1)
{
LONG lLength;
QuitIfFail(pDoc->QueryInterface(IID_IXMLDOMNode, (void**)&pParentNode));
QuitIfFail(pParentNode->selectNodes(bstrName, &m_ppNodeListArray[dwIndex1]));
if (NULL == m_ppNodeListArray[dwIndex1])
{
goto CleanUp;
}
QuitIfFail(m_ppNodeListArray[dwIndex1]->get_length(&lLength));
if (lLength <= 0)
{
goto CleanUp;
}
dwIndex2 = GetNodeHandle();
if (HANDLE_NODE_INVALID != dwIndex2)
{
QuitIfFail(m_ppNodeListArray[dwIndex1]->nextNode(&m_ppNodeArray[dwIndex2]));
if (NULL == m_ppNodeArray[dwIndex2])
{
goto CleanUp;
}
*phNode = dwIndex2;
SafeReleaseNULL(pParentNode);
return dwIndex1;
}
}
CleanUp:
*phNode = HANDLE_NODE_INVALID;
SafeReleaseNULL(pParentNode);
return HANDLE_NODELIST_INVALID;
}
/////////////////////////////////////////////////////////////////////////////
// FindNextDOMNode()
//
// Retrieve the next xml node with the given tag name under the given parent node
/////////////////////////////////////////////////////////////////////////////
HRESULT CIUXml::FindNextDOMNode(HANDLE_NODELIST hNodeList, IXMLDOMNode** ppNode)
{
HRESULT hr = E_FAIL;
if (HANDLE_NODELIST_INVALID != hNodeList)
{
hr = m_ppNodeListArray[hNodeList]->nextNode(ppNode);
}
if (FAILED(hr) || NULL == *ppNode)
{
*ppNode = NULL;
return E_FAIL;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// FindNextDOMNode()
//
// Retrieve the handle of next xml node with the given tag name under the given parent node
/////////////////////////////////////////////////////////////////////////////
HRESULT CIUXml::FindNextDOMNode(HANDLE_NODELIST hNodeList, HANDLE_NODE* phNode)
{
HRESULT hr = E_FAIL;
DWORD dwIndex = HANDLE_NODE_INVALID;
if (HANDLE_NODELIST_INVALID != hNodeList)
{
dwIndex = GetNodeHandle();
if (HANDLE_NODE_INVALID != dwIndex)
{
hr = m_ppNodeListArray[hNodeList]->nextNode(&m_ppNodeArray[dwIndex]);
}
}
if (FAILED(hr) || NULL == m_ppNodeArray[dwIndex])
{
*phNode = HANDLE_NODE_INVALID;
return E_FAIL;
}
*phNode = dwIndex;
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CreateDOMNodeWithHandle()
//
// Create an xml node of the given type
// Return: index of the node array "m_ppNodeArray"; or -1 if failure.
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODE CIUXml::CreateDOMNodeWithHandle(IXMLDOMDocument* pDoc, SHORT nType, BSTR bstrName, BSTR bstrNamespaceURI /*= NULL*/)
{
USES_IU_CONVERSION;
HRESULT hr = S_OK;
if (NULL == pDoc)
{
hr = E_INVALIDARG;
return HANDLE_NODE_INVALID;
}
DWORD dwIndex;
VARIANT vType;
VariantInit(&vType);
vType.vt = VT_I2;
vType.iVal = nType;
dwIndex = GetNodeHandle();
if (HANDLE_NODE_INVALID != dwIndex)
{
QuitIfFail(pDoc->createNode(vType, bstrName, bstrNamespaceURI, &m_ppNodeArray[dwIndex]));
return dwIndex;
}
CleanUp:
return HANDLE_NODE_INVALID;
}
/////////////////////////////////////////////////////////////////////////////
// CXmlSystemSpec
/////////////////////////////////////////////////////////////////////////////
// Constructor
//
// Create IXMLDOMDocument* for SystemSpec
/////////////////////////////////////////////////////////////////////////////
CXmlSystemSpec::CXmlSystemSpec()
: m_pDocSystemSpec(NULL),
m_pNodeSystemInfo(NULL),
m_pNodeComputerSystem(NULL),
m_pNodeRegKeysSW(NULL),
m_pNodePlatform(NULL),
m_pNodeDevices(NULL)
{
LOG_Block("CXmlSystemSpec()");
HRESULT hr = CoCreateInstance(CLSID_DOMDocument,
NULL,
CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument,
(void **) &m_pDocSystemSpec);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
else
{
IXMLDOMNode* pNodeXML = NULL;
BSTR bstrNameSpaceSchema = NULL;
//
// create the <?xml version="1.0"?> node
//
pNodeXML = CreateDOMNode(m_pDocSystemSpec, NODE_PROCESSING_INSTRUCTION, KEY_XML);
if (NULL == pNodeXML) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocSystemSpec, pNodeXML));
//
// process the iuident.txt to find the SystemSpec schema path
//
TCHAR szIUDir[MAX_PATH];
TCHAR szIdentFile[MAX_PATH];
LPTSTR pszSystemSpecSchema = NULL;
LPTSTR pszNameSpaceSchema = NULL;
pszSystemSpecSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
if (NULL == pszSystemSpecSchema)
{
LOG_ErrorMsg(E_OUTOFMEMORY);
goto CleanUp;
}
pszNameSpaceSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
if (NULL == pszNameSpaceSchema)
{
LOG_ErrorMsg(E_OUTOFMEMORY);
goto CleanUp;
}
GetIndustryUpdateDirectory(szIUDir);
hr = PathCchCombine(szIdentFile, ARRAYSIZE(szIdentFile), szIUDir,IDENTTXT);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
if (GetPrivateProfileString(IDENT_IUSCHEMA,
IDENT_IUSCHEMA_SYSTEMSPEC,
_T(""),
pszSystemSpecSchema,
INTERNET_MAX_URL_LENGTH,
szIdentFile) == INTERNET_MAX_URL_LENGTH - 1)
{
LOG_Error(_T("SystemSpec schema buffer overflow"));
goto CleanUp;
}
if ('\0' == pszSystemSpecSchema[0])
{
// no SystemSpec schema path specified in iuident.txt
LOG_Error(_T("No schema path specified in iuident.txt for SystemSpec"));
goto CleanUp;
}
hr = StringCchPrintfEx(pszNameSpaceSchema, INTERNET_MAX_URL_LENGTH, NULL, NULL, MISTSAFE_STRING_FLAGS,
_T("x-schema:%s"), pszSystemSpecSchema);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
bstrNameSpaceSchema = T2BSTR(pszNameSpaceSchema);
//
// create the <systemInfo> node with the path of the schema
//
m_pNodeSystemInfo = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_SYSTEMINFO, bstrNameSpaceSchema);
SafeSysFreeString(bstrNameSpaceSchema);
if (NULL == m_pNodeSystemInfo) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocSystemSpec, m_pNodeSystemInfo));
CleanUp:
SafeReleaseNULL(pNodeXML);
SafeHeapFree(pszSystemSpecSchema);
SafeHeapFree(pszNameSpaceSchema);
}
}
/////////////////////////////////////////////////////////////////////////////
// Destructor
//
// Release IXMLDOMDocument* for SystemSpec
/////////////////////////////////////////////////////////////////////////////
CXmlSystemSpec::~CXmlSystemSpec()
{
SafeReleaseNULL(m_pNodeDevices);
SafeReleaseNULL(m_pNodePlatform);
SafeReleaseNULL(m_pNodeRegKeysSW);
SafeReleaseNULL(m_pNodeComputerSystem);
SafeReleaseNULL(m_pNodeSystemInfo);
SafeReleaseNULL(m_pDocSystemSpec);
}
/////////////////////////////////////////////////////////////////////////////
// AddComputerSystem()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddComputerSystem(BSTR bstrManufacturer,
BSTR bstrModel,
BSTR bstrSupportSite /*= NULL*/,
INT iAdmin /*= -1*/,
INT iWUDisabled /*= -1*/,
INT iAUEnabled /*= -1*/,
BSTR bstrPID)
{
LOG_Block("AddComputerSystem()");
HRESULT hr = E_FAIL;
m_pNodeComputerSystem = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_COMPUTERSYSTEM);
if (NULL == m_pNodeComputerSystem) return hr;
//
// Manufacturer and Model are now optional (RAID#337879 IU: can't get latest IU controls to work with IU site)
//
if (NULL != bstrManufacturer)
{
ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_MANUFACTURER, bstrManufacturer));
}
if (NULL != bstrModel)
{
ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_MODEL, bstrModel));
}
if (NULL != bstrSupportSite)
{
ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_SUPPORTSITE, bstrSupportSite));
}
if (NULL != bstrPID)
{
ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_PID, bstrPID));
}
if (-1 != iAdmin)
{
ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_ADMINISTRATOR, iAdmin));
}
if (-1 != iWUDisabled)
{
ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_WU_DISABLED, iWUDisabled));
}
if (-1 != iAUEnabled)
{
ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_AU_ENABLED, iAUEnabled));
}
ReturnIfFail(InsertNode(m_pNodeSystemInfo, m_pNodeComputerSystem));
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddDriveSpace()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddDriveSpace(BSTR bstrDrive, INT iKBytes)
{
LOG_Block("AddDriveSpace()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeDriveSpace = NULL;
pNodeDriveSpace = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_DRIVESPACE);
if (NULL == pNodeDriveSpace) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDriveSpace, KEY_DRIVE, bstrDrive));
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDriveSpace, KEY_KBYTES, iKBytes));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeComputerSystem, pNodeDriveSpace));
CleanUp:
SafeReleaseNULL(pNodeDriveSpace);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddReg()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddReg(BSTR bstrProvider)
{
LOG_Block("AddReg()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeRegKeys = NULL;
IXMLDOMNode* pNodeRegKeysHKLM = NULL;
IXMLDOMNode* pNodeRegValue = NULL;
IXMLDOMNode* pNodeRegValueText = NULL;
if (NULL == m_pNodeRegKeysSW)
{
//
// create the <regKeys> node
//
pNodeRegKeys = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_REGKEYS);
if (NULL == pNodeRegKeys) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeSystemInfo, pNodeRegKeys));
//
// create the <HKEY_LOCAL_MACHINE> node
//
pNodeRegKeysHKLM = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_REG_HKLM);
if (NULL == pNodeRegKeysHKLM) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeRegKeys, pNodeRegKeysHKLM));
//
// create the <SOFTWARE> node
//
m_pNodeRegKeysSW = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_REG_SW);
if (NULL == m_pNodeRegKeysSW) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeRegKeysHKLM, m_pNodeRegKeysSW));
}
//
// add the <value> node
//
pNodeRegValue = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_VALUE);
if (NULL == pNodeRegValue) goto CleanUp;
pNodeRegValueText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL);
if (NULL == pNodeRegValueText) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(SetValue(pNodeRegValueText, bstrProvider));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeRegValue, pNodeRegValueText));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeRegKeysSW, pNodeRegValue));
CleanUp:
if (FAILED(hr))
SafeReleaseNULL(m_pNodeRegKeysSW);
SafeReleaseNULL(pNodeRegKeys);
SafeReleaseNULL(pNodeRegKeysHKLM);
SafeReleaseNULL(pNodeRegValue);
SafeReleaseNULL(pNodeRegValueText);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddPlatform()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddPlatform(BSTR bstrName)
{
LOG_Block("AddPlatform()");
HRESULT hr = E_FAIL;
m_pNodePlatform = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_PLATFORM);
if (NULL == m_pNodePlatform) return hr;
ReturnIfFail(SetAttribute(m_pNodePlatform, KEY_NAME, bstrName));
ReturnIfFail(InsertNode(m_pNodeSystemInfo, m_pNodePlatform));
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddProcessor()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddProcessor(BSTR bstrProcessor)
{
LOG_Block("AddProcessor()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeProcessor = NULL;
IXMLDOMNode* pNodeProcessorText = NULL;
pNodeProcessor = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_PROCESSORARCHITECTURE);
if (NULL == pNodeProcessor) goto CleanUp;
pNodeProcessorText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL);
if (NULL == pNodeProcessorText) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(SetValue(pNodeProcessorText, bstrProcessor));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeProcessor, pNodeProcessorText));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodePlatform, pNodeProcessor));
CleanUp:
SafeReleaseNULL(pNodeProcessor);
SafeReleaseNULL(pNodeProcessorText);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddVersion()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddVersion(INT iMajor /*= -1*/,
INT iMinor /*= -1*/,
INT iBuild /*= -1*/,
INT iSPMajor /*= -1*/,
INT iSPMinor /*= -1*/,
BSTR bstrTimeStamp /*= NULL*/)
{
LOG_Block("AddVersion()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeVersion = NULL;
//
// create the <version> node
//
pNodeVersion = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_VERSION);
if (NULL == pNodeVersion) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodePlatform, pNodeVersion));
//
// set the "major" attribute
//
if (-1 != iMajor)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_MAJOR, iMajor));
}
//
// set the "minor" attribute
//
if (-1 != iMinor)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_MINOR, iMinor));
}
//
// set the "build" attribute
//
if (-1 != iBuild)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_BUILD, iBuild));
}
//
// set the "servicePackMajor" attribute
//
if (-1 != iSPMajor)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_SERVICEPACKMAJOR, iSPMajor));
}
//
// set the "servicePackMinor" attribute
//
if (-1 != iSPMinor)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_SERVICEPACKMINOR, iSPMinor));
}
//
// set the "timestamp" attribute
//
if (NULL != bstrTimeStamp)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_TIMESTAMP, bstrTimeStamp));
}
CleanUp:
SafeReleaseNULL(pNodeVersion);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddSuite()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddSuite(BSTR bstrSuite)
{
LOG_Block("AddSuite()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeSuite = NULL;
IXMLDOMNode* pNodeSuiteText = NULL;
pNodeSuite = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_SUITE);
if (NULL == pNodeSuite) goto CleanUp;
pNodeSuiteText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL);
if (NULL == pNodeSuiteText) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(SetValue(pNodeSuiteText, bstrSuite));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeSuite, pNodeSuiteText));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodePlatform, pNodeSuite));
CleanUp:
SafeReleaseNULL(pNodeSuite);
SafeReleaseNULL(pNodeSuiteText);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddProductType()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddProductType(BSTR bstrProductType)
{
LOG_Block("AddProductType()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeProductType = NULL;
IXMLDOMNode* pNodeProductTypeText = NULL;
pNodeProductType = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_PRODUCTTYPE);
if (NULL == pNodeProductType) goto CleanUp;
pNodeProductTypeText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL);
if (NULL == pNodeProductTypeText) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(SetValue(pNodeProductTypeText, bstrProductType));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeProductType, pNodeProductTypeText));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodePlatform, pNodeProductType));
CleanUp:
SafeReleaseNULL(pNodeProductType);
SafeReleaseNULL(pNodeProductTypeText);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddLocale()
//
// We need to pass back a handle to differentiate different <locale> node
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddLocale(BSTR bstrContext, HANDLE_NODE* phNodeLocale)
{
LOG_Block("AddLocale()");
HRESULT hr = E_FAIL;
*phNodeLocale = CreateDOMNodeWithHandle(m_pDocSystemSpec, NODE_ELEMENT, KEY_LOCALE);
if (HANDLE_NODE_INVALID == *phNodeLocale) return hr;
hr = SetAttribute(m_ppNodeArray[*phNodeLocale], KEY_CONTEXT, bstrContext);
if (FAILED(hr))
{
SafeCloseHandleNode(*phNodeLocale);
LOG_ErrorMsg(hr);
return hr;
}
ReturnIfFail(InsertNode(m_pNodeSystemInfo, m_ppNodeArray[*phNodeLocale]));
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddLanguage()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddLanguage(HANDLE_NODE hNodeLocale, BSTR bstrLocale)
{
LOG_Block("AddLanguage()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeLanguage = NULL;
IXMLDOMNode* pNodeLanguageText = NULL;
pNodeLanguage = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_LANGUAGE);
if (NULL == pNodeLanguage) goto CleanUp;
pNodeLanguageText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL);
if (NULL == pNodeLanguageText) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(SetValue(pNodeLanguageText, bstrLocale));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeLanguage, pNodeLanguageText));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeLocale], pNodeLanguage));
CleanUp:
SafeReleaseNULL(pNodeLanguage);
SafeReleaseNULL(pNodeLanguageText);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddDevice()
//
// We need to pass back a handle to differentiate different <device> node
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddDevice(BSTR bstrDeviceInstance, /*= NULL - optional attribute*/
INT iIsPrinter /*= -1*/,
BSTR bstrProvider /*= NULL*/,
BSTR bstrMfgName /*= NULL*/,
BSTR bstrDriverName /*= NULL*/,
HANDLE_NODE* phNodeDevice)
{
LOG_Block("AddDevice()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodePrinterInfo = NULL;
if (NULL == m_pNodeDevices)
{
//
// create the <devices> node
//
m_pNodeDevices = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_DEVICES);
if (NULL == m_pNodeDevices) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeSystemInfo, m_pNodeDevices));
}
//
// add the <device> node
//
*phNodeDevice = CreateDOMNodeWithHandle(m_pDocSystemSpec, NODE_ELEMENT, KEY_DEVICE);
if (HANDLE_NODE_INVALID == *phNodeDevice) goto CleanUp;
if (NULL != bstrDeviceInstance && 0 < lstrlenW(bstrDeviceInstance))
{
//
// set optional deviceInstance attribute of <device>
//
CleanUpIfFailedAndSetHrMsg(SetAttribute(m_ppNodeArray[*phNodeDevice], KEY_DEVICEINSTANCE, bstrDeviceInstance));
}
if (-1 != iIsPrinter)
{
//
// set isPrinter attribute of <device>
//
CleanUpIfFailedAndSetHrMsg(SetAttribute(m_ppNodeArray[*phNodeDevice], KEY_ISPRINTER, iIsPrinter));
//
// Add a <printerInfo> node within <device>
//
pNodePrinterInfo = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_PRINTERINFO);
if (NULL != pNodePrinterInfo)
{
if (NULL != bstrProvider)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodePrinterInfo, KEY_DRIVERPROVIDER, bstrProvider));
}
if (NULL != bstrMfgName)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodePrinterInfo, KEY_MFGNAME, bstrMfgName));
}
if (NULL != bstrDriverName)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodePrinterInfo, KEY_DRIVERNAME, bstrDriverName));
}
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[*phNodeDevice], pNodePrinterInfo));
}
}
//
// insert to <devices>
//
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeDevices, m_ppNodeArray[*phNodeDevice]));
CleanUp:
SafeReleaseNULL(pNodePrinterInfo);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddHWID()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::AddHWID(HANDLE_NODE hNodeDevice,
BOOL fIsCompatible,
UINT iRank,
BSTR bstrHWID,
BSTR bstrDriverVer /*= NULL*/)
{
LOG_Block("AddHWID()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeHWID = NULL;
IXMLDOMNode* pNodeHWIDText = NULL;
BSTR bstrNameHWID = NULL;
if (fIsCompatible)
{
bstrNameHWID = SysAllocString(L"compid");
}
else
{
bstrNameHWID = SysAllocString(L"hwid");
}
pNodeHWID = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, bstrNameHWID);
if (NULL == pNodeHWID) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeHWID, KEY_RANK, iRank));
if (NULL != bstrDriverVer)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeHWID, KEY_DRIVERVER, bstrDriverVer));
}
pNodeHWIDText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL);
if (NULL == pNodeHWIDText) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(SetValue(pNodeHWIDText, bstrHWID));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeHWID, pNodeHWIDText));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeDevice], pNodeHWID));
CleanUp:
SafeReleaseNULL(pNodeHWID);
SafeReleaseNULL(pNodeHWIDText);
SysFreeString(bstrNameHWID);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetSystemSpecBSTR()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemSpec::GetSystemSpecBSTR(BSTR *pbstrXmlSystemSpec)
{
LOG_Block("GetSystemSpecBSTR()");
//
// convert XML DOC into BSTR
//
HRESULT hr = m_pDocSystemSpec->get_xml(pbstrXmlSystemSpec);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CXmlSystemClass
/////////////////////////////////////////////////////////////////////////////
// Constructor
//
// Create IXMLDOMDocument* for SystemInfoClasses
/////////////////////////////////////////////////////////////////////////////
CXmlSystemClass::CXmlSystemClass()
: m_pDocSystemClass(NULL)
{
}
/////////////////////////////////////////////////////////////////////////////
// Destructor
//
// Release IXMLDOMDocument* for SystemInfoClasses
/////////////////////////////////////////////////////////////////////////////
CXmlSystemClass::~CXmlSystemClass()
{
SafeReleaseNULL(m_pDocSystemClass);
}
/////////////////////////////////////////////////////////////////////////////
// LoadXMLDocument()
//
// Load an XML Document from string
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlSystemClass::LoadXMLDocument(BSTR bstrXml, BOOL fOfflineMode)
{
LOG_Block("LoadXMLDocument()");
SafeReleaseNULL(m_pDocSystemClass);
HRESULT hr = LoadXMLDoc(bstrXml, &m_pDocSystemClass, fOfflineMode);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetClasses()
//
// Return the bitmap of existence of all possible system info classes
/////////////////////////////////////////////////////////////////////////////
DWORD CXmlSystemClass::GetClasses()
{
LOG_Block("GetClasses()");
DWORD dwResult = 0;
IXMLDOMNodeList* pNodeList = NULL;
BSTR bstrNameComputerSystem = SysAllocString(L"classes/computerSystem");
BSTR bstrNameRegKeys = SysAllocString(L"classes/regKeys");
BSTR bstrNamePlatform = SysAllocString(L"classes/platform");
BSTR bstrNameLocale = SysAllocString(L"classes/locale");
BSTR bstrNameDevices = SysAllocString(L"classes/devices");
pNodeList = FindDOMNodeList(m_pDocSystemClass, bstrNameComputerSystem);
if (NULL != pNodeList)
{
dwResult |= COMPUTERSYSTEM;
SafeReleaseNULL(pNodeList);
}
pNodeList = FindDOMNodeList(m_pDocSystemClass, bstrNameRegKeys);
if (NULL != pNodeList)
{
dwResult |= REGKEYS;
SafeReleaseNULL(pNodeList);
}
pNodeList = FindDOMNodeList(m_pDocSystemClass, bstrNamePlatform);
if (NULL != pNodeList)
{
dwResult |= PLATFORM;
SafeReleaseNULL(pNodeList);
}
pNodeList = FindDOMNodeList(m_pDocSystemClass, bstrNameLocale);
if (NULL != pNodeList)
{
dwResult |= LOCALE;
SafeReleaseNULL(pNodeList);
}
pNodeList = FindDOMNodeList(m_pDocSystemClass, bstrNameDevices);
if (NULL != pNodeList)
{
dwResult |= DEVICES;
SafeReleaseNULL(pNodeList);
}
SysFreeString(bstrNameComputerSystem);
SysFreeString(bstrNameRegKeys);
SysFreeString(bstrNamePlatform);
SysFreeString(bstrNameLocale);
SysFreeString(bstrNameDevices);
return dwResult;
}
/////////////////////////////////////////////////////////////////////////////
// CXmlCatalog
/////////////////////////////////////////////////////////////////////////////
// Constructor
//
// Create IXMLDOMDocument* for Catalog
/////////////////////////////////////////////////////////////////////////////
CXmlCatalog::CXmlCatalog()
: m_pDocCatalog(NULL)
{
}
/////////////////////////////////////////////////////////////////////////////
// Destructor
//
// Release IXMLDOMDocument* for Catalog
/////////////////////////////////////////////////////////////////////////////
CXmlCatalog::~CXmlCatalog()
{
SafeReleaseNULL(m_pDocCatalog);
}
/////////////////////////////////////////////////////////////////////////////
// LoadXMLDocument()
//
// Load an XML Document from string
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::LoadXMLDocument(BSTR bstrXml, BOOL fOfflineMode)
{
LOG_Block("LoadXMLDocument()");
SafeReleaseNULL(m_pDocCatalog);
HRESULT hr = LoadXMLDoc(bstrXml, &m_pDocCatalog, fOfflineMode);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemCount()
//
// Gets a Count of How Many Items are in this Catalog
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetItemCount(LONG *plItemCount)
{
LOG_Block("GetItemCount()");
HRESULT hr = E_FAIL;
IXMLDOMNodeList *pItemList = NULL;
QuitIfNull(plItemCount);
QuitIfNull(m_pDocCatalog);
IXMLDOMNode *pParentNode = NULL;
CleanUpIfFailedAndSetHrMsg(m_pDocCatalog->QueryInterface(IID_IXMLDOMNode, (void**)&pParentNode));
CleanUpIfFailedAndSetHrMsg(pParentNode->selectNodes(KEY_ITEM_SEARCH, &pItemList));
if (NULL == pItemList) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(pItemList->get_length(plItemCount));
CleanUp:
SafeReleaseNULL(pParentNode);
SafeReleaseNULL(pItemList);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetProviders()
//
// Find a list of <provider> node in catalog xml
/////////////////////////////////////////////////////////////////////////////
IXMLDOMNodeList* CXmlCatalog::GetProviders()
{
LOG_Block("GetProviders()");
IXMLDOMNodeList* pNodeList = NULL;
pNodeList = FindDOMNodeList(m_pDocCatalog, KEY_CATALOG_PROVIDER);
return pNodeList;
}
/////////////////////////////////////////////////////////////////////////////
// GetFirstProvider()
//
// Find the first provider in catalog xml doc
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CXmlCatalog::GetFirstProvider(HANDLE_NODE* phNodeProvider)
{
LOG_Block("GetFirstProvider()");
HANDLE_NODELIST hNodeListProvider = FindFirstDOMNode(m_pDocCatalog, KEY_CATALOG_PROVIDER, phNodeProvider);
return hNodeListProvider;
}
/////////////////////////////////////////////////////////////////////////////
// GetNextProvider()
//
// Find the next provider in catalog xml doc
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetNextProvider(HANDLE_NODELIST hNodeListProvider, HANDLE_NODE* phNodeProvider)
{
LOG_Block("GetNextProvider()");
return FindNextDOMNode(hNodeListProvider, phNodeProvider);
}
/////////////////////////////////////////////////////////////////////////////
// GetFirstItem()
//
// Find the first item in provider (parent) node
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CXmlCatalog::GetFirstItem(HANDLE_NODE hNodeProvider, HANDLE_NODE* phNodeItem)
{
LOG_Block("GetFirstItem()");
HANDLE_NODELIST hNodeListItem = FindFirstDOMNode(m_ppNodeArray[hNodeProvider], KEY_ITEM, phNodeItem);
return hNodeListItem;
}
/////////////////////////////////////////////////////////////////////////////
// GetNextItem()
//
// Find the next item in provider (parent) node
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetNextItem(HANDLE_NODELIST hNodeListItem, HANDLE_NODE* phNodeItem)
{
LOG_Block("GetNextItem()");
return FindNextDOMNode(hNodeListItem, phNodeItem);
}
/////////////////////////////////////////////////////////////////////////////
// GetFirstItemDependency()
//
// Find the first dependency item in Item Dependencies node
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CXmlCatalog::GetFirstItemDependency(HANDLE_NODE hNodeItem, HANDLE_NODE* phNodeItem)
{
LOG_Block("GetFirstItemDependency");
HRESULT hr;
QuitIfNull(phNodeItem);
IXMLDOMNode* pNodeDependencies = NULL;
IXMLDOMNode* pNodeIdentity = NULL;
HANDLE_NODELIST hNodeListItem = HANDLE_NODELIST_INVALID;
hr = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_DEPENDENCIES, &pNodeDependencies);
QuitIfFail(hr);
hNodeListItem = FindFirstDOMNode(pNodeDependencies, KEY_IDENTITY, &pNodeIdentity);
if (HANDLE_NODELIST_INVALID != hNodeListItem)
{
// We found at least one Identity in this Dependencies key, Try to find the matching
// Item in the Catalog and if found return as the phNodeItem
FindItemByIdentity(pNodeIdentity, phNodeItem);
}
CleanUp:
SafeReleaseNULL(pNodeIdentity);
SafeReleaseNULL(pNodeDependencies);
return hNodeListItem;
}
/////////////////////////////////////////////////////////////////////////////
// GetNextItemDependency()
//
// Find the next dependency item in the Item Dependencies node
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetNextItemDependency(HANDLE_NODELIST hNodeListItem, HANDLE_NODE* phNodeItem)
{
LOG_Block("GetNextItemDependency");
HRESULT hr;
QuitIfNull(phNodeItem);
IXMLDOMNode* pNodeIdentity = NULL;
hr = FindNextDOMNode(hNodeListItem, &pNodeIdentity);
// This function is supposed to return S_FALSE when no more items are available
// but FindNextDOMNode returns E_FAIL when it can't find the next node. So we won't
// look at the return.
// CleanUpIfFailedAndMsg(hr);
if (NULL != pNodeIdentity)
{
// We found another Identity in this Dependencies Key
hr = FindItemByIdentity(pNodeIdentity, phNodeItem);
}
else
{
hr = S_FALSE; // indicate to caller there are no more identities.
}
SafeReleaseNULL(pNodeIdentity);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CloseItemList()
//
// Release the item nodelist
/////////////////////////////////////////////////////////////////////////////
void CXmlCatalog::CloseItemList(HANDLE_NODELIST hNodeListItem)
{
SafeFindCloseHandle(hNodeListItem);
}
/////////////////////////////////////////////////////////////////////////////
// GetIdentity()
//
// Retrieve the unique name (identity) of the given provider or item
/////////////////////////////////////////////////////////////////////////////
//
// public version
//
HRESULT CXmlCatalog::GetIdentity(HANDLE_NODE hNode,
BSTR* pbstrName,
BSTR* pbstrPublisherName,
BSTR* pbstrGUID)
{
LOG_Block("GetIdentity()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeIdentity = NULL;
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNode], KEY_IDENTITY, &pNodeIdentity));
hr = Get3IdentiStrFromIdentNode(pNodeIdentity, pbstrName, pbstrPublisherName, pbstrGUID);
CleanUp:
SafeReleaseNULL(pNodeIdentity);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetIdentityStr()
//
// Retrieve the string that can be used to uniquely identify an object
// based on its <identity> node.
//
// This function defines the logic about what components can be used
// to define the uniqueness of an item based on the 3 parts of data from
// GetIdentity().
//
// The created string will be language neutral. That is, it can not
// ensure the uniqueness for two items having the same <identity> node
// except different only on <langauge> part inside <identity>
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetIdentityStr(HANDLE_NODE hNode,
BSTR* pbstrUniqIdentifierString)
{
IXMLDOMNode* pIdentityNode = NULL;
HRESULT hr = E_INVALIDARG;
if (FindNode(m_ppNodeArray[hNode], KEY_IDENTITY, &pIdentityNode) && NULL != pIdentityNode)
{
hr = UtilGetUniqIdentityStr(pIdentityNode, pbstrUniqIdentifierString, 0x0);
SafeReleaseNULL(pIdentityNode);
}
return hr;
}
HRESULT CXmlCatalog::GetIdentityStrForPing(HANDLE_NODE hNode,
BSTR* pbstrUniqIdentifierString)
{
IXMLDOMNode* pIdentityNode = NULL;
HRESULT hr = E_INVALIDARG;
if (FindNode(m_ppNodeArray[hNode], KEY_IDENTITY, &pIdentityNode) && NULL != pIdentityNode)
{
//
// first, based on OP team's requirement, we try to look for <itemId> in the identity tag.
// if it's there, use use that. If not, we use the publisherName.itemname thing.
//
if (FAILED(hr = GetAttribute(pIdentityNode, KEY_ITEMID, pbstrUniqIdentifierString)) || NULL == *pbstrUniqIdentifierString)
{
// hr = UtilGetUniqIdentityStr(pIdentityNode, pbstrUniqIdentifierString, SKIP_SERVICEPACK_VER);
hr = E_INVALIDARG;
}
SafeReleaseNULL(pIdentityNode);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetBSTRItemForCallback()
//
// Create an item node as the passed-in node, have child nodes identity and
// platform (anything uniquely idenitify this item) then output this
// item node data as string, then delete the crated node
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetBSTRItemForCallback(HANDLE_NODE hItem, BSTR* pbstrXmlItemForCallback)
{
HRESULT hr = E_INVALIDARG;
IXMLDOMNode* pNewItemNode = NULL;
IXMLDOMNode* pNewIdentityNode = NULL;
IXMLDOMNode* pNewPlatformNode = NULL;
IXMLDOMNode* pOldIdentityNode = NULL;
IXMLDOMNode* pOldPlatformNode = NULL;
IXMLDOMNode* p1 = NULL, *p2 = NULL;
LOG_Block("CXmlCatalog::GetBSTRItemForCallback()");
if (FAILED(hr = m_ppNodeArray[hItem]->cloneNode(VARIANT_FALSE, &pNewItemNode)) ||
FAILED(hr = FindSingleDOMNode(m_ppNodeArray[hItem], KEY_IDENTITY, &pOldIdentityNode)) ||
NULL == pOldIdentityNode ||
FAILED(hr = pOldIdentityNode->cloneNode(VARIANT_TRUE, &pNewIdentityNode)) ||
NULL == pNewIdentityNode ||
FAILED(hr = pNewItemNode->appendChild(pNewIdentityNode, &p1)) || NULL == p1)
{
if (S_FALSE == hr)
hr = E_INVALIDARG;
LOG_ErrorMsg(hr);
goto CleanUp;
}
//
// platform is optional
//
FindSingleDOMNode(m_ppNodeArray[hItem], KEY_PLATFORM, &pOldPlatformNode);
if (pOldPlatformNode)
{
if (FAILED(hr = pOldPlatformNode->cloneNode(VARIANT_TRUE, &pNewPlatformNode)) ||
NULL == pNewPlatformNode ||
FAILED(hr = pNewItemNode->appendChild(pNewPlatformNode, &p2)) || NULL == p2)
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
}
pNewItemNode->get_xml(pbstrXmlItemForCallback);
CleanUp:
SafeReleaseNULL(pOldIdentityNode);
SafeReleaseNULL(pOldPlatformNode);
SafeReleaseNULL(pNewIdentityNode);
SafeReleaseNULL(pNewPlatformNode);
SafeReleaseNULL(p1);
SafeReleaseNULL(p2);
SafeReleaseNULL(pNewItemNode);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// IsPrinterDriver()
//
// Retrieves from the Catalog whether this Item is a Printer Driver
//
/////////////////////////////////////////////////////////////////////////////
BOOL CXmlCatalog::IsPrinterDriver(HANDLE_NODE hNode)
{
LOG_Block("IsPrinterDriver()");
BOOL fRet = FALSE;
HRESULT hr;
IXMLDOMNode* pNodeDetection = NULL;
IXMLDOMNode* pNodeCompatibleHardware = NULL;
IXMLDOMNode* pNodeDevice = NULL;
hr = FindSingleDOMNode(m_ppNodeArray[hNode], KEY_DETECTION, &pNodeDetection);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeDetection, KEY_COMPATIBLEHARDWARE, &pNodeCompatibleHardware);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeCompatibleHardware, KEY_DEVICE, &pNodeDevice);
CleanUpIfFailedAndMsg(hr);
int intIsPrinter = 0;
GetAttribute(pNodeDevice, KEY_ISPRINTER, &intIsPrinter);
if (1 == intIsPrinter)
{
fRet = TRUE;
}
else
{
fRet = FALSE;
}
CleanUp:
SafeReleaseNULL(pNodeDevice);
SafeReleaseNULL(pNodeCompatibleHardware);
SafeReleaseNULL(pNodeDetection);
return fRet;
}
/////////////////////////////////////////////////////////////////////////////
// GetDriverInfo()
//
// Retrieves the Driver Information from the Catalog for this Item. Returns
// the Display Name and HWID for this driver - This is passed to the CDM
// installer
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetDriverInfo(HANDLE_NODE hNode,
BSTR* pbstrHWID,
BSTR* pbstrDisplayName)
{
HRESULT hr;
LOG_Block("GetDriverInfo()");
QuitIfNull(pbstrHWID);
QuitIfNull(pbstrDisplayName);
*pbstrHWID = NULL;
*pbstrDisplayName = NULL;
IXMLDOMNode* pNodeDetection = NULL;
IXMLDOMNode* pNodeCompatibleHardware = NULL;
IXMLDOMNode* pNodeDevice = NULL;
IXMLDOMNode* pNodeHWID = NULL;
IXMLDOMNode* pNodeDescription = NULL;
IXMLDOMNode* pNodeDescriptionText = NULL;
IXMLDOMNode* pNodeTitle = NULL;
hr = FindSingleDOMNode(m_ppNodeArray[hNode], KEY_DETECTION, &pNodeDetection);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeDetection, KEY_COMPATIBLEHARDWARE, &pNodeCompatibleHardware);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeCompatibleHardware, KEY_DEVICE, &pNodeDevice);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeDevice, KEY_HWID, &pNodeHWID);
CleanUpIfFailedAndMsg(hr);
GetText(pNodeHWID, pbstrHWID);
hr = FindSingleDOMNode(pNodeDetection, KEY_DESCRIPTION, &pNodeDescription);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeDescription, KEY_DESCRIPTIONTEXT, &pNodeDescriptionText);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeDescriptionText, KEY_TITLE, &pNodeTitle);
CleanUpIfFailedAndMsg(hr);
GetText(pNodeTitle, pbstrDisplayName);
CleanUp:
if (FAILED(hr))
{
SafeSysFreeString(*pbstrHWID);
SafeSysFreeString(*pbstrDisplayName);
}
SafeReleaseNULL(pNodeTitle);
SafeReleaseNULL(pNodeDescriptionText);
SafeReleaseNULL(pNodeDescription);
SafeReleaseNULL(pNodeHWID);
SafeReleaseNULL(pNodeDevice);
SafeReleaseNULL(pNodeCompatibleHardware);
SafeReleaseNULL(pNodeDetection);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetPrinterDriverInfo()
//
// Retrieves the Printer Driver Information from the Catalog for this Item.
// Returns the DriverName and the Architecture - This is passed to the CDM
// installer
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetPrinterDriverInfo(HANDLE_NODE hNode,
BSTR* pbstrDriverName,
BSTR* pbstrArchitecture)
{
HRESULT hr;
LOG_Block("GetPrinterDriverInfo()");
QuitIfNull(pbstrDriverName);
QuitIfNull(pbstrArchitecture);
IXMLDOMNode* pNodeDetection = NULL;
IXMLDOMNode* pNodeCompatibleHardware = NULL;
IXMLDOMNode* pNodeDevice = NULL;
IXMLDOMNode* pNodePrinterInfo = NULL;
hr = FindSingleDOMNode(m_ppNodeArray[hNode], KEY_DETECTION, &pNodeDetection);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeDetection, KEY_COMPATIBLEHARDWARE, &pNodeCompatibleHardware);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeCompatibleHardware, KEY_DEVICE, &pNodeDevice);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeDevice, KEY_PRINTERINFO, &pNodePrinterInfo);
CleanUpIfFailedAndMsg(hr);
GetAttribute(pNodePrinterInfo, KEY_DRIVERNAME, pbstrDriverName);
// NOTE: Currently the CatalogSchema site is not returning
// architecture for printers, and the schema doesn't require it
// CDM is using a default string for now based on compile architecture
// so we'll leave pbstrArchitecture NULL..
CleanUp:
SafeReleaseNULL(pNodePrinterInfo);
SafeReleaseNULL(pNodeDevice);
SafeReleaseNULL(pNodeCompatibleHardware);
SafeReleaseNULL(pNodeDetection);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetDriverInfoEx()
//
// Combines functionality of IsPrinterDriver, GetDriverInfo, and
// GetPrinterDriverInfo plus retreives MfgName and DriverProvider.
// Used by FindMatchingDriver()
//
// If SUCCEEDES pbstrHWID, pbstrDriverVer, and pbstrDisplayName
// are always returned.
// If SUCCEEDES && *pFIsPrinter == TRUE then pbstrDriverName,
// pbstrDriverProvider, and pbstrMfgName are returned.
//
// Currently pbstrArchitecture is never returned.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetDriverInfoEx( HANDLE_NODE hNode,
BOOL* pfIsPrinter,
BSTR* pbstrHWID,
BSTR* pbstrDriverVer,
BSTR* pbstrDisplayName,
BSTR* pbstrDriverName,
BSTR* pbstrDriverProvider,
BSTR* pbstrMfgName,
BSTR* pbstrArchitecture)
{
HRESULT hr;
LOG_Block("GetDriverInfoEx()");
QuitIfNull(pbstrHWID);
QuitIfNull(pbstrDriverVer);
QuitIfNull(pbstrDisplayName);
QuitIfNull(pbstrDriverName);
QuitIfNull(pbstrDriverProvider);
QuitIfNull(pbstrMfgName);
QuitIfNull(pbstrArchitecture);
*pbstrHWID = NULL;
*pbstrDriverVer = NULL;
*pbstrDisplayName = NULL;
*pbstrDriverName = NULL;
*pbstrDriverProvider = NULL;
*pbstrMfgName = NULL;
*pbstrArchitecture = NULL;
IXMLDOMNode* pNodeDetection = NULL;
IXMLDOMNode* pNodeCompatibleHardware = NULL;
IXMLDOMNode* pNodeDevice = NULL;
IXMLDOMNode* pNodeHWID = NULL;
IXMLDOMNode* pNodeDescription = NULL;
IXMLDOMNode* pNodeDescriptionText = NULL;
IXMLDOMNode* pNodeTitle = NULL;
IXMLDOMNode* pNodePrinterInfo = NULL;
hr = FindSingleDOMNode(m_ppNodeArray[hNode], KEY_DETECTION, &pNodeDetection);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeDetection, KEY_COMPATIBLEHARDWARE, &pNodeCompatibleHardware);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeCompatibleHardware, KEY_DEVICE, &pNodeDevice);
CleanUpIfFailedAndMsg(hr);
//
// Is it a printer?
//
int intIsPrinter = 0;
GetAttribute(pNodeDevice, KEY_ISPRINTER, &intIsPrinter);
if (1 == intIsPrinter)
{
*pfIsPrinter = TRUE;
}
else
{
*pfIsPrinter = FALSE;
}
//
// HWID and Driver Description
//
hr = FindSingleDOMNode(pNodeDevice, KEY_HWID, &pNodeHWID);
CleanUpIfFailedAndMsg(hr);
hr = GetText(pNodeHWID, pbstrHWID);
CleanUpIfFailedAndMsg(hr);
hr = GetAttribute(pNodeHWID, KEY_DRIVERVER, pbstrDriverVer);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(m_ppNodeArray[hNode], KEY_DESCRIPTION, &pNodeDescription);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeDescription, KEY_DESCRIPTIONTEXT, &pNodeDescriptionText);
CleanUpIfFailedAndMsg(hr);
hr = FindSingleDOMNode(pNodeDescriptionText, KEY_TITLE, &pNodeTitle);
CleanUpIfFailedAndMsg(hr);
hr = GetText(pNodeTitle, pbstrDisplayName);
CleanUpIfFailedAndMsg(hr);
if (*pfIsPrinter)
{
//
// Printer Attributes
//
hr = FindSingleDOMNode(pNodeDevice, KEY_PRINTERINFO, &pNodePrinterInfo);
CleanUpIfFailedAndMsg(hr);
hr = GetAttribute(pNodePrinterInfo, KEY_DRIVERNAME, pbstrDriverName);
CleanUpIfFailedAndMsg(hr);
hr = GetAttribute(pNodePrinterInfo, KEY_DRIVERPROVIDER, pbstrDriverProvider);
CleanUpIfFailedAndMsg(hr);
hr = GetAttribute(pNodePrinterInfo, KEY_MFGNAME, pbstrMfgName);
CleanUpIfFailedAndMsg(hr);
// NOTE: Currently the CatalogSchema site is not returning
// architecture for printers, and the schema doesn't require it
// CDM is using a default string for now based on compile architecture
// so we'll leave pbstrArchitecture NULL..
}
CleanUp:
if (FAILED(hr))
{
SafeSysFreeString(*pbstrHWID);
SafeSysFreeString(*pbstrDriverVer);
SafeSysFreeString(*pbstrDisplayName);
SafeSysFreeString(*pbstrDriverName);
SafeSysFreeString(*pbstrDriverProvider);
SafeSysFreeString(*pbstrMfgName);
SafeSysFreeString(*pbstrArchitecture);
}
SafeReleaseNULL(pNodeTitle);
SafeReleaseNULL(pNodeDescriptionText);
SafeReleaseNULL(pNodeDescription);
SafeReleaseNULL(pNodeHWID);
SafeReleaseNULL(pNodeDevice);
SafeReleaseNULL(pNodeCompatibleHardware);
SafeReleaseNULL(pNodeDetection);
SafeReleaseNULL(pNodePrinterInfo);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemPlatformStr()
//
// The input node pointer points to a node has <identity> as its child.
// This function will retrieve the <platform> node from <identity> and
// convert the data inside <platform> into a string that can be used to
// uniquely identify a platform.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetItemFirstPlatformStr(HANDLE_NODE hNodeItem,
BSTR* pbstrPlatform)
{
HRESULT hr;
IXMLDOMNode* pNodePlatform = NULL;
LOG_Block("GetItemFirstPlatformStr");
USES_IU_CONVERSION;
//
// get the first platform node from this item node
//
hr = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_PLATFORM, &pNodePlatform);
CleanUpIfFailedAndMsg(hr);
//
// get platform data from this ndoe and convert it into string
//
hr = GetPlatformStrForPing(pNodePlatform, pbstrPlatform);
CleanUp:
SafeReleaseNULL(pNodePlatform);
//
// since platform is not a required element in <item>, so we should not
// return error if not found
//
if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) == hr)
{
*pbstrPlatform = NULL;
hr = S_FALSE;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemAllPlatformStr()
//
// The input node pointer points to an item node that has <platform> node(s).
// This function will retrieve every <platform> node from this item node and
// convert the data inside <platform> into a string that can be used to
// uniquely identify a platform.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetItemAllPlatformStr(HANDLE_NODE hNodeItem,
BSTR** ppbPlatforms, UINT* pnPlatformCount)
{
LOG_Block("GetItemAllPlatformStr");
HRESULT hr;
IXMLDOMNodeList* pPlatformList = NULL;
IXMLDOMElement* pElement = NULL;
IXMLDOMNode* pNodePlatform = NULL;
long lCount = 0;
int i;
BSTR* pbstrPlatformList = NULL;
//
// get list of platform nodes
//
hr = m_ppNodeArray[hNodeItem]->QueryInterface(IID_IXMLDOMElement, (void**)&pElement);
CleanUpIfFailedAndMsg(hr);
hr = pElement->getElementsByTagName(KEY_PLATFORM, &pPlatformList);
CleanUpIfFailedAndMsg(hr);
hr = pPlatformList->get_length(&lCount);
CleanUpIfFailedAndMsg(hr);
if (0 == lCount)
{
goto CleanUp;
}
pbstrPlatformList = (BSTR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lCount * sizeof(BSTR*));
CleanUpFailedAllocSetHrMsg(pbstrPlatformList);
//
// loop through each suite, if any
//
pPlatformList->reset();
for (i = 0; i < lCount; i++)
{
hr = pPlatformList->get_item(i, &pNodePlatform);
CleanUpIfFailedAndMsg(hr);
if (pNodePlatform)
{
hr = pNodePlatform->get_text(&(pbstrPlatformList[i]));
CleanUpIfFailedAndMsg(hr);
pNodePlatform->Release();
pNodePlatform = NULL;
}
}
hr = S_OK;
CleanUp:
SafeReleaseNULL(pNodePlatform);
SafeReleaseNULL(pPlatformList);
SafeReleaseNULL(pElement);
if (SUCCEEDED(hr))
{
*pnPlatformCount = lCount;
*ppbPlatforms = pbstrPlatformList;
}
else
{
if (NULL != pbstrPlatformList)
{
*pnPlatformCount = 0;
//
// release all possibly allocated memory
//
for (i = 0; i < lCount; i++)
{
SafeSysFreeString(pbstrPlatformList[i]);
}
HeapFree(GetProcessHeap(), 0, pbstrPlatformList);
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemPlatformStr()
//
// The input node pointer points to a node has <identity> as its child.
// This function will retrieve the <platform> node from <identity> and
// convert the data inside <platform> into a string that can be used to
// uniquely identify a platform.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetPlatformStr(IXMLDOMNode* pNodePlatform,
BSTR* pbstrPlatform)
{
return UtilGetPlatformStr(pNodePlatform, pbstrPlatform, 0x0);
}
HRESULT CXmlCatalog::GetPlatformStrForPing(IXMLDOMNode* pNodePlatform,
BSTR* pbstrPlatform)
{
return UtilGetPlatformStr(pNodePlatform, pbstrPlatform, SKIP_SUITES | SKIP_SERVICEPACK_VER);
}
/////////////////////////////////////////////////////////////////////////////
//
// get data from a version node and convert them into a string with
// format:
// VersionStr = <Version>[,<SvcPackVer>[,<timeStamp>]]
// <Version> = <Major>[.<Minor>[.<Build>]]
// <SvcPackVer> = <Major>[.<minor>]
//
// Assumption:
// pszVersion points to a buffer LARGE ENOUGH to store
// any legal version number.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::getVersionStr(IXMLDOMNode* pNodeVersion, LPTSTR pszVersion)
{
return UtilGetVersionStr(pNodeVersion, pszVersion, 0x0);
}
HRESULT CXmlCatalog::getVersionStrWithoutSvcPack(IXMLDOMNode* pNodeVersion, LPTSTR pszVersion)
{
return UtilGetVersionStr(pNodeVersion, pszVersion, SKIP_SERVICEPACK_VER);
}
/////////////////////////////////////////////////////////////////////////////
// GetItemFirstLanguageStr()
//
// The input node pointer points to a node has <identity> as its child.
// This function will retrieve the first <language> node from <identity>
// node
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetItemFirstLanguageStr(HANDLE_NODE hNodeItem,
BSTR* pbstrLanguage)
{
LOG_Block("GetItemFirstLanguageStr");
IXMLDOMNode* pNodeIdentity = NULL;
IXMLDOMNode* pNodeLanguage = NULL;
HRESULT hr = m_ppNodeArray[hNodeItem]->selectSingleNode(KEY_IDENTITY, &pNodeIdentity);
CleanUpIfFailedAndMsg(hr);
if (pNodeIdentity)
{
if (HANDLE_NODELIST_INVALID == FindFirstDOMNode(pNodeIdentity, KEY_LANGUAGE, &pNodeLanguage))
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
goto CleanUp;
}
else
{
hr = pNodeLanguage->get_text(pbstrLanguage);
CleanUpIfFailedAndMsg(hr);
}
}
CleanUp:
SafeReleaseNULL(pNodeLanguage);
SafeReleaseNULL(pNodeIdentity);
//
// since language is not a required element in <identity>, so we should not
// return error if not found
//
if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) == hr)
{
*pbstrLanguage = NULL;
hr = S_FALSE;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemAllLanguageStr()
//
// The input node pointer points to a node has <identity> as its child.
// This function will retrieve every <language> node from <identity> node and
// convert the data into an BSTR array to return.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetItemAllLanguageStr(HANDLE_NODE hNodeItem,
BSTR** ppbstrLanguage, UINT* pnLangCount)
{
LOG_Block("GetItemAllLanguageStr");
HRESULT hr;
IXMLDOMNode* pNodeIdentity = NULL;
IXMLDOMNodeList* pLanguageList = NULL;
IXMLDOMElement* pElement = NULL;
IXMLDOMNode* pNodeLanguage = NULL;
long lCount = 0;
int i;
BSTR* pbstrLanguageList = NULL;
hr = m_ppNodeArray[hNodeItem]->selectSingleNode(KEY_IDENTITY, &pNodeIdentity);
CleanUpIfFailedAndMsg(hr);
//
// get list of nodes
//
hr = pNodeIdentity->QueryInterface(IID_IXMLDOMElement, (void**)&pElement);
CleanUpIfFailedAndMsg(hr);
hr = pElement->getElementsByTagName(KEY_LANGUAGE, &pLanguageList);
CleanUpIfFailedAndMsg(hr);
hr = pLanguageList->get_length(&lCount);
CleanUpIfFailedAndMsg(hr);
if (0 == lCount)
{
goto CleanUp;
}
pbstrLanguageList = (BSTR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lCount * sizeof(BSTR*));
CleanUpFailedAllocSetHrMsg(pbstrLanguageList);
//
// loop through each suite, if any
//
pLanguageList->reset();
for (i = 0; i < lCount; i++)
{
hr = pLanguageList->get_item(i, &pNodeLanguage);
CleanUpIfFailedAndMsg(hr);
if (pNodeLanguage)
{
hr = pNodeLanguage->get_text(&(pbstrLanguageList[i]));
CleanUpIfFailedAndMsg(hr);
pNodeLanguage->Release();
pNodeLanguage = NULL;
}
}
hr = S_OK;
CleanUp:
SafeReleaseNULL(pNodeLanguage);
SafeReleaseNULL(pLanguageList);
SafeReleaseNULL(pElement);
SafeReleaseNULL(pNodeIdentity);
if (SUCCEEDED(hr))
{
*pnLangCount = lCount;
*ppbstrLanguage = pbstrLanguageList;
}
else
{
if (NULL != pbstrLanguageList)
{
*pnLangCount = 0;
//
// release all possibly allocated memory
//
for (i = 0; i < lCount; i++)
{
SafeSysFreeString(pbstrLanguageList[i]);
}
HeapFree(GetProcessHeap(), 0, pbstrLanguageList);
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemFirstCodeBase()
//
// Find the first codebase (path) of the given item
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CXmlCatalog::GetItemFirstCodeBase(HANDLE_NODE hNodeItem,
BSTR* pbstrCodeBase,
BSTR* pbstrName,
BSTR* pbstrCRC,
BOOL* pfPatchAvailable,
LONG* plSize)
{
LOG_Block("GetItemFirstCodeBase()");
HRESULT hr = E_FAIL;
QuitIfNull(pbstrCodeBase);
QuitIfNull(pbstrName);
QuitIfNull(pbstrCRC);
QuitIfNull(pfPatchAvailable);
QuitIfNull(plSize);
IXMLDOMNode* pNodeInstall = NULL;
IXMLDOMNode* pNodeCodeBaseSize = NULL;
HANDLE_NODE hNodeCodeBase = HANDLE_NODE_INVALID;
HANDLE_NODELIST hNodeListCodeBase = HANDLE_NODELIST_INVALID;
*pbstrCodeBase = NULL;
*pbstrName = NULL;
*pbstrCRC = NULL;
*pfPatchAvailable = FALSE;
*plSize = -1;
BSTR bstrSize = NULL;
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_INSTALLATION, &pNodeInstall));
hNodeListCodeBase = FindFirstDOMNode(pNodeInstall, KEY_CODEBASE, &hNodeCodeBase);
if (HANDLE_NODELIST_INVALID == hNodeListCodeBase) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_HREF, pbstrCodeBase));
CleanUpIfFailedAndSetHrMsg(GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_PATCHAVAILABLE, pfPatchAvailable));
GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_CRC, pbstrCRC); // optional attribute, don't fail if its not there.
GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_NAME, pbstrName);
FindSingleDOMNode(m_ppNodeArray[hNodeCodeBase], KEY_SIZE, &pNodeCodeBaseSize);
GetText(pNodeCodeBaseSize, &bstrSize);
if (NULL != bstrSize)
{
*plSize = MyBSTR2L(bstrSize);
SysFreeString(bstrSize);
}
CleanUp:
SafeReleaseNULL(pNodeInstall);
SafeReleaseNULL(pNodeCodeBaseSize);
if (FAILED(hr))
{
SafeSysFreeString(*pbstrCodeBase);
SafeSysFreeString(*pbstrName);
SafeSysFreeString(*pbstrCRC);
*pfPatchAvailable = FALSE;
*plSize = -1;
}
return hNodeListCodeBase;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemNextCodeBase()
//
// Find the next codebase (path) of the given item
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetItemNextCodeBase(HANDLE_NODELIST hNodeListCodeBase,
BSTR* pbstrCodeBase,
BSTR* pbstrName,
BSTR* pbstrCRC,
BOOL* pfPatchAvailable,
LONG* plSize)
{
LOG_Block("GetItemNextCodeBase()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeCodeBaseSize = NULL;
HANDLE_NODE hNodeCodeBase = HANDLE_NODE_INVALID;
if (NULL == pbstrCodeBase || NULL == pbstrName || NULL == pbstrCRC || NULL == pfPatchAvailable || NULL == plSize)
{
return E_INVALIDARG;
}
*pbstrCodeBase = NULL;
*pbstrName = NULL;
*pbstrCRC = NULL;
*pfPatchAvailable = FALSE;
*plSize = -1;
BSTR bstrSize = NULL;
if (SUCCEEDED(hr = FindNextDOMNode(hNodeListCodeBase, &hNodeCodeBase)))
{
CleanUpIfFailedAndSetHrMsg(GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_HREF, pbstrCodeBase));
CleanUpIfFailedAndSetHrMsg(GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_PATCHAVAILABLE, pfPatchAvailable));
GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_NAME, pbstrName);
GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_CRC, pbstrCRC);
FindSingleDOMNode(m_ppNodeArray[hNodeCodeBase], KEY_SIZE, &pNodeCodeBaseSize);
GetText(pNodeCodeBaseSize, &bstrSize);
if (NULL != bstrSize)
{
*plSize = MyBSTR2L(bstrSize);
}
}
CleanUp:
SafeReleaseNULL(pNodeCodeBaseSize);
SafeSysFreeString(bstrSize);
if (FAILED(hr))
{
SafeSysFreeString(*pbstrCodeBase);
SafeSysFreeString(*pbstrCRC);
SafeSysFreeString(*pbstrName);
*pfPatchAvailable = FALSE;
*plSize = -1;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemInstallInfo()
//
// Retrieve the installation information of the given item
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetItemInstallInfo(HANDLE_NODE hNodeItem,
BSTR* pbstrInstallerType,
BOOL* pfExclusive,
BOOL* pfReboot,
LONG* plNumCommands)
{
LOG_Block("GetItemInstallInfo()");
HRESULT hr = E_FAIL;
QuitIfNull(pbstrInstallerType);
QuitIfNull(pfExclusive);
QuitIfNull(pfReboot);
QuitIfNull(plNumCommands);
*pbstrInstallerType = NULL;
*plNumCommands = 0; // may not be any, so initialize to 0
IXMLDOMNode* pNodeInstall = NULL;
IXMLDOMNodeList* pNodeListCommands = NULL;
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_INSTALLATION, &pNodeInstall));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstall, KEY_INSTALLERTYPE, pbstrInstallerType));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstall, KEY_EXCLUSIVE, pfExclusive));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstall, KEY_NEEDSREBOOT, pfReboot));
pNodeListCommands = FindDOMNodeList(pNodeInstall, KEY_COMMAND);
if (NULL != pNodeListCommands)
{
CleanUpIfFailedAndSetHrMsg(pNodeListCommands->get_length(plNumCommands));
}
CleanUp:
if (FAILED(hr))
{
SafeSysFreeString(*pbstrInstallerType);
}
SafeReleaseNULL(pNodeInstall);
SafeReleaseNULL(pNodeListCommands);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemInstallCommand()
//
// Find the installation command and switches of the given item
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetItemInstallCommand(HANDLE_NODE hNodeItem,
INT iOrder,
BSTR* pbstrCommandType,
BSTR* pbstrCommand,
BSTR* pbstrSwitches,
BSTR* pbstrInfSection)
{
LOG_Block("GetItemInstallCommand()");
USES_IU_CONVERSION;
HRESULT hr = E_FAIL;
QuitIfNull(pbstrCommandType);
QuitIfNull(pbstrCommand);
QuitIfNull(pbstrSwitches);
QuitIfNull(pbstrInfSection);
*pbstrCommandType = NULL;
*pbstrCommand = NULL;
*pbstrSwitches = NULL;
*pbstrInfSection = NULL;
IXMLDOMNode* pNodeInstall = NULL;
IXMLDOMNode* pNodeCommand = NULL;
IXMLDOMNode* pNodeSwitches = NULL;
BSTR bstrNameCommandTemp = SysAllocString(L"command[@order = ");
TCHAR szCommand[64];
hr = StringCchPrintfEx(szCommand, ARRAYSIZE(szCommand), NULL, NULL, MISTSAFE_STRING_FLAGS,
_T("%ls\"%d\"]"), bstrNameCommandTemp, iOrder);
CleanUpIfFailedAndSetHrMsg(hr);
BSTR bstrNameCommand = SysAllocString(T2OLE(szCommand));
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_INSTALLATION, &pNodeInstall));
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeInstall, bstrNameCommand, &pNodeCommand));
CleanUpIfFailedAndSetHrMsg(GetText(pNodeCommand, pbstrCommand));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeCommand, KEY_COMMANDTYPE, pbstrCommandType));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeCommand, KEY_INFINSTALL, pbstrInfSection));
if (SUCCEEDED(FindSingleDOMNode(pNodeCommand, KEY_SWITCHES, &pNodeSwitches)))
{
CleanUpIfFailedAndSetHrMsg(GetText(pNodeSwitches, pbstrSwitches));
}
CleanUp:
if (FAILED(hr))
{
SafeSysFreeString(*pbstrCommandType);
SafeSysFreeString(*pbstrCommand);
SafeSysFreeString(*pbstrSwitches);
SafeSysFreeString(*pbstrInfSection);
}
SafeReleaseNULL(pNodeInstall);
SafeReleaseNULL(pNodeCommand);
SafeReleaseNULL(pNodeSwitches);
SysFreeString(bstrNameCommand);
SysFreeString(bstrNameCommandTemp);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CloseItem()
//
// Release the item node
/////////////////////////////////////////////////////////////////////////////
void CXmlCatalog::CloseItem(HANDLE_NODE hNodeItem)
{
SafeCloseHandleNode(hNodeItem);
}
/////////////////////////////////////////////////////////////////////////////
// GetTotalEstimatedSize()
//
// Get the Total Estimated Download Size of all Items based on Codebase Size
HRESULT CXmlCatalog::GetTotalEstimatedSize(LONG *plTotalSize)
{
LOG_Block("GetTotalEstimatedSize()");
HRESULT hr = E_FAIL;
BSTR bstrCodebaseSize = NULL;
IXMLDOMNodeList *pItemList = NULL;
IXMLDOMNodeList *pCodebaseList = NULL;
IXMLDOMNode *pNodeItem = NULL;
IXMLDOMNode *pNodeInstall = NULL;
IXMLDOMNode *pNodeCodebase = NULL;
IXMLDOMNode *pNodeSize = NULL;
LONG lItemCount = 0;
LONG lCodebaseCount = 0;
LONG lTotalSize = 0;
QuitIfNull(plTotalSize);
*plTotalSize = 0;
IXMLDOMNode *pParentNode = NULL;
CleanUpIfFailedAndSetHrMsg(m_pDocCatalog->QueryInterface(IID_IXMLDOMNode, (void**)&pParentNode));
CleanUpIfFailedAndSetHrMsg(pParentNode->selectNodes(KEY_ITEM_SEARCH, &pItemList));
if (NULL == pItemList) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(pItemList->get_length(&lItemCount));
if (0 == lItemCount) goto CleanUp; // no items
// Loop through each Item
CleanUpIfFailedAndSetHrMsg(pItemList->nextNode(&pNodeItem));
while (NULL != pNodeItem)
{
// Get Installation Element
CleanUpIfFailedAndSetHrMsg(pNodeItem->selectSingleNode(KEY_INSTALLATION, &pNodeInstall));
if (NULL == pNodeInstall) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(pNodeInstall->selectNodes(KEY_CODEBASE, &pCodebaseList));
if (NULL == pCodebaseList) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(pCodebaseList->get_length(&lCodebaseCount));
if (0 == lCodebaseCount) goto CleanUp; // must be at least 1 cab
// Loop through each Codebase Getting the Size for Each one
CleanUpIfFailedAndSetHrMsg(pCodebaseList->nextNode(&pNodeCodebase));
while (NULL != pNodeCodebase)
{
// Get the Size Element
CleanUpIfFailedAndSetHrMsg(pNodeCodebase->selectSingleNode(KEY_SIZE, &pNodeSize));
if (NULL != pNodeSize)
{
pNodeSize->get_text(&bstrCodebaseSize);
if (NULL != bstrCodebaseSize)
{
// Add this Codebase's size to the total download size
lTotalSize += (DWORD) MyBSTR2L(bstrCodebaseSize);
SafeSysFreeString(bstrCodebaseSize);
}
}
SafeReleaseNULL(pNodeSize);
SafeReleaseNULL(pNodeCodebase);
CleanUpIfFailedAndSetHrMsg(pCodebaseList->nextNode(&pNodeCodebase));
}
SafeReleaseNULL(pCodebaseList);
SafeReleaseNULL(pNodeInstall);
SafeReleaseNULL(pNodeItem);
CleanUpIfFailedAndSetHrMsg(pItemList->nextNode(&pNodeItem)); // get the next Item Node
}
// Update the Total Size after completing.. if we fail anywhere through here
// we'll return 0.
*plTotalSize = lTotalSize;
CleanUp:
SafeReleaseNULL(pParentNode);
SafeReleaseNULL(pItemList);
SafeReleaseNULL(pCodebaseList);
SafeReleaseNULL(pNodeItem);
SafeReleaseNULL(pNodeInstall);
SafeReleaseNULL(pNodeCodebase);
SafeReleaseNULL(pNodeSize);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// FindItemByIdentity()
//
// Input:
// pNodeIdentity - a pointer to an Identity Node to match against an Items
// identity in the Catalog. We will search through each item
// till we find a match with the supplied identity
//
// Output:
// phNodeItem - Handle of the found Item
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::FindItemByIdentity(IXMLDOMNode* pNodeIdentity, HANDLE_NODE* phNodeItem)
{
LOG_Block("FindItemByIdentity()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeIdentityDes = NULL;
*phNodeItem = HANDLE_NODE_INVALID;
HANDLE_NODE hNodeItem = HANDLE_NODE_INVALID;
HANDLE_NODELIST hNodeList = HANDLE_NODELIST_INVALID;
hNodeList = FindFirstDOMNode(m_pDocCatalog, KEY_ITEM_SEARCH, &hNodeItem);
if (HANDLE_NODELIST_INVALID != hNodeList)
{
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_IDENTITY, &pNodeIdentityDes));
if (AreNodesEqual(pNodeIdentityDes, pNodeIdentity))
{
*phNodeItem = hNodeItem;
goto CleanUp;
}
SafeReleaseNULL(pNodeIdentityDes);
SafeReleaseNULL(m_ppNodeArray[hNodeItem]);
while (SUCCEEDED(FindNextDOMNode(hNodeList, &hNodeItem)))
{
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_IDENTITY, &pNodeIdentityDes));
if (AreNodesEqual(pNodeIdentityDes, pNodeIdentity))
{
*phNodeItem = hNodeItem;
goto CleanUp;
}
SafeReleaseNULL(pNodeIdentityDes);
SafeReleaseNULL(m_ppNodeArray[hNodeItem]);
}
}
CleanUp:
CloseItemList(hNodeList);
SafeReleaseNULL(pNodeIdentityDes);
if (HANDLE_NODE_INVALID == *phNodeItem)
{
LOG_Error(_T("Can't find the matching Item Node in Catalog"));
hr = E_FAIL;
}
return hr;
}
/*
/////////////////////////////////////////////////////////////////////////////
// IfSameIdentity()
//
// Return TRUE if the two <identity> nodes are identical. Return FALSE otherwise.
/////////////////////////////////////////////////////////////////////////////
BOOL CXmlCatalog::IfSameIdentity(IXMLDOMNode* pNodeIdentity1, IXMLDOMNode* pNodeIdentity2)
{
LOG_Block("IfSameIdentity()");
BOOL fResult = FALSE;
BSTR bstrNameGUID = SysAllocString(L"guid");
BSTR bstrNameIDName = SysAllocString(L"name");
BSTR bstrNameIDPublisherName = SysAllocString(L"publisherName");
BSTR bstrNameType = SysAllocString(L"type");
BSTR bstrNameVersion = SysAllocString(L"version");
BSTR bstrNameLanguage = SysAllocString(L"language");
//
// compare <guid> node
//
if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameGUID))
{
goto CleanUp;
}
//
// compare <publisherName> node
//
if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameIDPublisherName))
{
goto CleanUp;
}
//
// compare "name" attribute, this is a required attribute
//
if (!IfHasSameAttribute(pNodeIdentity1, pNodeIdentity2, bstrNameIDName, FALSE))
{
goto CleanUp;
}
//
// compare <type> node
//
if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameType))
{
goto CleanUp;
}
//
// compare <version> node, which really means "file version" here
//
if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameVersion))
{
goto CleanUp;
}
//
// compare <language> node
//
if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameLanguage))
{
goto CleanUp;
}
fResult = TRUE;
CleanUp:
SysFreeString(bstrNameGUID);
SysFreeString(bstrNameIDName);
SysFreeString(bstrNameIDPublisherName);
SysFreeString(bstrNameType);
SysFreeString(bstrNameVersion);
SysFreeString(bstrNameLanguage);
if (!fResult)
{
LOG_XML(_T("Different <identity>\'s found."));
}
else
{
LOG_XML(_T("Same <identity>\'s found."));
}
return fResult;
}
*/
/////////////////////////////////////////////////////////////////////////////
// GetItemLanguage()
//
// Get the Language Entity from the Item Identity
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetItemLanguage(HANDLE_NODE hNodeItem, BSTR* pbstrLanguage)
{
HRESULT hr = S_OK;
if (HANDLE_NODE_INVALID == hNodeItem || NULL == pbstrLanguage)
{
return E_INVALIDARG;
}
IXMLDOMNode *pNodeIdentity = NULL;
IXMLDOMNode *pNodeLanguage = NULL;
hr = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_IDENTITY, &pNodeIdentity);
if (FAILED(hr))
goto CleanUp;
hr = FindSingleDOMNode(pNodeIdentity, KEY_LANGUAGE, &pNodeLanguage);
if (FAILED(hr))
goto CleanUp;
hr = GetText(pNodeLanguage, pbstrLanguage);
if (FAILED(hr))
goto CleanUp;
CleanUp:
SafeReleaseNULL(pNodeLanguage);
SafeReleaseNULL(pNodeIdentity);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetCorpItemPlatformStr()
//
// Get the Simplified Platform String for an Item (uses the first available platform element)
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlCatalog::GetCorpItemPlatformStr(HANDLE_NODE hNodeItem, BSTR* pbstrPlatformStr)
{
HRESULT hr = S_OK;
if (HANDLE_NODE_INVALID == hNodeItem || NULL == pbstrPlatformStr)
{
return E_INVALIDARG;
}
IXMLDOMNode *pNodePlatform = NULL;
IXMLDOMNode *pNodePlatformArchitecture = NULL;
IXMLDOMNode *pNodePlatformVersion = NULL;
BSTR bstrPlatformName = NULL;
BSTR bstrArchitecture = NULL;
int iMajor = 0;
int iMinor = 0;
hr = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_PLATFORM, &pNodePlatform);
if (FAILED(hr))
goto CleanUp;
hr = GetAttribute(pNodePlatform, KEY_NAME, &bstrPlatformName);
if (FAILED(hr))
goto CleanUp;
hr = FindSingleDOMNode(pNodePlatform, KEY_PROCESSORARCHITECTURE, &pNodePlatformArchitecture);
if (FAILED(hr))
goto CleanUp;
hr = FindSingleDOMNode(pNodePlatform, KEY_VERSION, &pNodePlatformVersion);
if (FAILED(hr))
goto CleanUp;
if (NULL != bstrPlatformName && 0 != SysStringLen(bstrPlatformName))
{
if (CSTR_EQUAL == CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE,
bstrPlatformName, -1, L"VER_PLATFORM_WIN32_NT", -1))
{
// this is an NT platform
hr = GetAttribute(pNodePlatformVersion, KEY_MAJOR, &iMajor);
if (FAILED(hr))
goto CleanUp;
if (4 == iMajor)
{
// WinNT4
*pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_NT4);
}
else // 5 == iMajor
{
hr = GetAttribute(pNodePlatformVersion, KEY_MINOR, &iMinor);
if (FAILED(hr))
goto CleanUp;
if (iMinor > 0)
{
hr = GetText(pNodePlatformArchitecture, &bstrArchitecture);
if (FAILED(hr))
goto CleanUp;
// whistler
if (CSTR_EQUAL == CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE,
bstrArchitecture, -1, L"x86", -1))
{
// x86WinXP
*pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_X86WHI);
}
else
{
// ia64WinXP
*pbstrPlatformStr = SysAllocString(CORP_PLATFROM_DIR_IA64WHI);
}
}
else
{
// x86Win2k
*pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_NT5);
}
}
}
else // VER_PLATFORM_WIN32_WINDOWS
{
// this is a Win9x platform
hr = GetAttribute(pNodePlatformVersion, KEY_MINOR, &iMinor);
if (FAILED(hr))
goto CleanUp;
if (iMinor >= 90)
{
// x86WinME
*pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_WINME);
}
else if (iMinor > 0 && iMinor < 90)
{
// x86Win98
*pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_W98);
}
else
{
// x86Win95
*pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_W95);
}
}
}
CleanUp:
SysFreeString(bstrPlatformName);
SysFreeString(bstrArchitecture);
SafeReleaseNULL(pNodePlatformVersion);
SafeReleaseNULL(pNodePlatformArchitecture);
SafeReleaseNULL(pNodePlatform);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CXmlItems
/////////////////////////////////////////////////////////////////////////////
// Constructor
//
// Create IXMLDOMDocument* for Items; this is for write only
/////////////////////////////////////////////////////////////////////////////
CXmlItems::CXmlItems()
: m_pDocItems(NULL),
m_pNodeItems(NULL)
{
LOG_Block("CXmlItems()");
Init();
}
/////////////////////////////////////////////////////////////////////////////
// Constructor
//
// Create IXMLDOMDocument* for Items; take TRUE for read, FALSE for write
/////////////////////////////////////////////////////////////////////////////
CXmlItems::CXmlItems(BOOL fRead)
: m_pDocItems(NULL),
m_pNodeItems(NULL)
{
LOG_Block("CXmlItems(BOOL fRead)");
//
// for writing Items only
//
if (!fRead)
{
Init();
}
}
/////////////////////////////////////////////////////////////////////////////
//
// Initialize XML DOC node pointers before writing
/////////////////////////////////////////////////////////////////////////////
void CXmlItems::Init()
{
LOG_Block("Init()");
HRESULT hr = CoCreateInstance(CLSID_DOMDocument,
NULL,
CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument,
(void **) &m_pDocItems);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
else
{
IXMLDOMNode* pNodeXML = NULL;
BSTR bstrNameSpaceSchema = NULL;
//
// create the <?xml version="1.0"?> node
//
pNodeXML = CreateDOMNode(m_pDocItems, NODE_PROCESSING_INSTRUCTION, KEY_XML);
if (NULL == pNodeXML) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, pNodeXML));
//
// process the iuident.txt to find the Items schema path
//
TCHAR szIUDir[MAX_PATH];
TCHAR szIdentFile[MAX_PATH];
LPTSTR pszItemsSchema = NULL;
LPTSTR pszNameSpaceSchema = NULL;
pszItemsSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
if (NULL == pszItemsSchema)
{
LOG_ErrorMsg(E_OUTOFMEMORY);
goto CleanUp;
}
pszNameSpaceSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
if (NULL == pszNameSpaceSchema)
{
LOG_ErrorMsg(E_OUTOFMEMORY);
goto CleanUp;
}
GetIndustryUpdateDirectory(szIUDir);
hr = PathCchCombine(szIdentFile, ARRAYSIZE(szIdentFile), szIUDir, IDENTTXT);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
GetPrivateProfileString(IDENT_IUSCHEMA,
IDENT_IUSCHEMA_ITEMS,
_T(""),
pszItemsSchema,
INTERNET_MAX_URL_LENGTH,
szIdentFile);
if ('\0' == pszItemsSchema[0])
{
// no Items schema path specified in iuident.txt
LOG_Error(_T("No schema path specified in iuident.txt for Items"));
goto CleanUp;
}
hr = StringCchPrintfEx(pszNameSpaceSchema, INTERNET_MAX_URL_LENGTH, NULL, NULL, MISTSAFE_STRING_FLAGS,
_T("x-schema:%s"), pszItemsSchema);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
bstrNameSpaceSchema = T2BSTR(pszNameSpaceSchema);
//
// create the <items> node with the path of the schema
//
m_pNodeItems = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_ITEMS, bstrNameSpaceSchema);
if (NULL == m_pNodeItems) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, m_pNodeItems));
CleanUp:
SafeReleaseNULL(pNodeXML);
SysFreeString(bstrNameSpaceSchema);
SafeHeapFree(pszItemsSchema);
SafeHeapFree(pszNameSpaceSchema);
}
}
/////////////////////////////////////////////////////////////////////////////
// Destructor
//
// Release IXMLDOMDocument* for Items
/////////////////////////////////////////////////////////////////////////////
CXmlItems::~CXmlItems()
{
SafeReleaseNULL(m_pNodeItems);
SafeReleaseNULL(m_pDocItems);
}
/////////////////////////////////////////////////////////////////////////////
// Clear()
//
// Reset IXMLDOMDocument* for Items
/////////////////////////////////////////////////////////////////////////////
void CXmlItems::Clear()
{
SafeReleaseNULL(m_pNodeItems);
SafeReleaseNULL(m_pDocItems);
}
/////////////////////////////////////////////////////////////////////////////
// LoadXMLDocument()
//
// Load an XML Document from string
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::LoadXMLDocument(BSTR bstrXml)
{
LOG_Block("LoadXMLDocument()");
SafeReleaseNULL(m_pDocItems);
HRESULT hr = LoadXMLDoc(bstrXml, &m_pDocItems);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// LoadXMLDocumentFile()
//
// Load an XML Document from the specified file
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::LoadXMLDocumentFile(BSTR bstrFilePath)
{
LOG_Block("LoadXMLDocumentFile()");
SafeReleaseNULL(m_pDocItems);
HRESULT hr = LoadDocument(bstrFilePath, &m_pDocItems);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// SaveXMLDocument()
//
// Save an XML Document to the specified location
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::SaveXMLDocument(BSTR bstrFilePath)
{
LOG_Block("SaveXMLDocument()");
HRESULT hr = SaveDocument(m_pDocItems, bstrFilePath);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddGlobalErrorCodeIfNoItems()
//
// Add the errorCode attribute for <items> if there's no <itemStatus> child node
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CXmlItems::AddGlobalErrorCodeIfNoItems(DWORD dwErrorCode)
{
LOG_Block("AddGlobalErrorCodeIfNoItems()");
HRESULT hr = S_OK;
IXMLDOMNode* pNodeItem = NULL;
HANDLE_NODE hNodeItemStatus = HANDLE_NODE_INVALID;
FindFirstDOMNode(m_pDocItems, KEY_ITEM_ITEMSTATUS, &hNodeItemStatus);
if (HANDLE_NODE_INVALID == hNodeItemStatus)
{
//
// set the "errorCode" attribute
//
FindFirstDOMNode(m_pDocItems, KEY_ITEMS, &pNodeItem);
if (NULL != pNodeItem)
{
hr = SetAttribute(pNodeItem, KEY_ERRORCODE, dwErrorCode);
}
}
SafeReleaseNULL(pNodeItem);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetFirstItem()
//
// Find the first item in Items xml doc
/////////////////////////////////////////////////////////////////////////////
HANDLE_NODELIST CXmlItems::GetFirstItem(HANDLE_NODE* phNodeItem)
{
LOG_Block("GetFirstItem()");
HANDLE_NODELIST hNodeListItem = FindFirstDOMNode(m_pDocItems, KEY_ITEM_ITEMSTATUS, phNodeItem);
return hNodeListItem;
}
/////////////////////////////////////////////////////////////////////////////
// GetNextItem()
//
// Find the next item in Items xml doc
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::GetNextItem(HANDLE_NODELIST hNodeListItem, HANDLE_NODE* phNodeItem)
{
LOG_Block("GetNextItem()");
return FindNextDOMNode(hNodeListItem, phNodeItem);
}
/////////////////////////////////////////////////////////////////////////////
// CloseItemList()
//
// Release the item nodelist
/////////////////////////////////////////////////////////////////////////////
void CXmlItems::CloseItemList(HANDLE_NODELIST hNodeListItem)
{
SafeFindCloseHandle(hNodeListItem);
}
/////////////////////////////////////////////////////////////////////////////
// GetItemDownloadPath()
//
// Retrieve the download path of the given item
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::GetItemDownloadPath(HANDLE_NODE hNodeItem, BSTR* pbstrDownloadPath)
{
LOG_Block("GetItemDownloadPath()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeDownloadPath = NULL;
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_DOWNLOADPATH, &pNodeDownloadPath));
CleanUpIfFailedAndSetHrMsg(GetText(pNodeDownloadPath, pbstrDownloadPath));
CleanUp:
SafeReleaseNULL(pNodeDownloadPath);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemDownloadPath()
//
// Retrieve the download path of the given item in catalog
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::GetItemDownloadPath(CXmlCatalog* pCatalog, HANDLE_NODE hNodeItem, BSTR* pbstrDownloadPath)
{
LOG_Block("GetItemDownloadPath() for an item in catalog");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeItem = NULL;
IXMLDOMNode* pNodeDownloadPath = NULL;
HANDLE_NODE hNodeItemsItem = HANDLE_NODE_INVALID;
if (NULL != (pNodeItem = pCatalog->GetDOMNodebyHandle(hNodeItem)))
{
hr = FindItem(pNodeItem, &hNodeItemsItem, TRUE);
}
else
{
LOG_Error(_T("Can't retrieve valid item node from catalog xml"));
hr = E_FAIL;
goto CleanUp;
}
if (FAILED(hr) || HANDLE_NODE_INVALID == hNodeItemsItem)
{
LOG_Error(_T("Can't find item from Items xml"));
goto CleanUp;
}
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItemsItem], KEY_DOWNLOADPATH, &pNodeDownloadPath));
CleanUpIfFailedAndSetHrMsg(GetText(pNodeDownloadPath, pbstrDownloadPath));
CleanUp:
SafeReleaseNULL(pNodeDownloadPath);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CloseItem()
//
// Release the item node
/////////////////////////////////////////////////////////////////////////////
void CXmlItems::CloseItem(HANDLE_NODE hNodeItem)
{
SafeCloseHandleNode(hNodeItem);
}
/////////////////////////////////////////////////////////////////////////////
// FindItem()
//
// Input:
// pNodeItem - the <itemStatus> node of the install items xml; we need
// to find the corresponding <itemStatus> node in the existing
// items xml with the identical <identity>, <platform> and
// <client> nodes.
// Output:
// phNodeItem - the handle we pass back to differentiate different
// <itemStatus> node in the existing items xml
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::FindItem(IXMLDOMNode* pNodeItem, HANDLE_NODE* phNodeItem, BOOL fIdentityOnly /*= FALSE*/)
{
LOG_Block("FindItem()");
HRESULT hr1, hr2, hr = E_FAIL;
IXMLDOMNode* pNodeIdentitySrc = NULL;
IXMLDOMNode* pNodeIdentityDes = NULL;
IXMLDOMNode* pNodePlatformSrc = NULL;
IXMLDOMNode* pNodePlatformDes = NULL;
IXMLDOMNode* pNodeClientSrc = NULL;
IXMLDOMNode* pNodeClientDes = NULL;
*phNodeItem = HANDLE_NODE_INVALID;
HANDLE_NODE hNodeItem = HANDLE_NODE_INVALID;
HANDLE_NODELIST hNodeList = HANDLE_NODELIST_INVALID;
hNodeList = FindFirstDOMNode(m_pDocItems, KEY_ITEM_ITEMSTATUS, &hNodeItem);
if (HANDLE_NODELIST_INVALID != hNodeList)
{
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_IDENTITY, &pNodeIdentityDes));
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_IDENTITY, &pNodeIdentitySrc));
if (AreNodesEqual(pNodeIdentityDes, pNodeIdentitySrc))
{
if (fIdentityOnly)
{
//
// we now found the match
//
*phNodeItem = hNodeItem;
goto CleanUp;
}
else
{
hr1 = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_PLATFORM, &pNodePlatformDes);
hr2 = FindSingleDOMNode(pNodeItem, KEY_PLATFORM, &pNodePlatformSrc);
if ((FAILED(hr1) && FAILED(hr2)) ||
(SUCCEEDED(hr1) && SUCCEEDED(hr2) && AreNodesEqual(pNodePlatformDes, pNodePlatformSrc)))
{
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_CLIENT, &pNodeClientDes));
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_CLIENT, &pNodeClientSrc));
if (AreNodesEqual(pNodeClientDes, pNodeClientSrc))
{
//
// we now found the match
//
*phNodeItem = hNodeItem;
goto CleanUp;
}
}
}
}
SafeReleaseNULL(pNodeClientDes);
SafeReleaseNULL(pNodeClientSrc);
SafeReleaseNULL(pNodePlatformDes);
SafeReleaseNULL(pNodePlatformSrc);
SafeReleaseNULL(pNodeIdentityDes);
SafeReleaseNULL(pNodeIdentitySrc);
SafeReleaseNULL(m_ppNodeArray[hNodeItem]);
while (SUCCEEDED(FindNextDOMNode(hNodeList, &hNodeItem)))
{
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_IDENTITY, &pNodeIdentityDes));
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_IDENTITY, &pNodeIdentitySrc));
if (AreNodesEqual(pNodeIdentityDes, pNodeIdentitySrc))
{
if (fIdentityOnly)
{
//
// we now found the match
//
*phNodeItem = hNodeItem;
goto CleanUp;
}
else
{
hr1 = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_PLATFORM, &pNodePlatformDes);
hr2 = FindSingleDOMNode(pNodeItem, KEY_PLATFORM, &pNodePlatformSrc);
if ((FAILED(hr1) && FAILED(hr2)) ||
(SUCCEEDED(hr1) && SUCCEEDED(hr2) && AreNodesEqual(pNodePlatformDes, pNodePlatformSrc)))
{
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_CLIENT, &pNodeClientDes));
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_CLIENT, &pNodeClientSrc));
if (AreNodesEqual(pNodeClientDes, pNodeClientSrc))
{
//
// we now found the match
//
*phNodeItem = hNodeItem;
break;
}
}
}
}
SafeReleaseNULL(pNodeClientDes);
SafeReleaseNULL(pNodeClientSrc);
SafeReleaseNULL(pNodePlatformDes);
SafeReleaseNULL(pNodePlatformSrc);
SafeReleaseNULL(pNodeIdentityDes);
SafeReleaseNULL(pNodeIdentitySrc);
SafeReleaseNULL(m_ppNodeArray[hNodeItem]);
}
}
CleanUp:
CloseItemList(hNodeList);
SafeReleaseNULL(pNodeClientDes);
SafeReleaseNULL(pNodeClientSrc);
SafeReleaseNULL(pNodePlatformDes);
SafeReleaseNULL(pNodePlatformSrc);
SafeReleaseNULL(pNodeIdentityDes);
SafeReleaseNULL(pNodeIdentitySrc);
if (HANDLE_NODE_INVALID == *phNodeItem)
{
LOG_Error(_T("Can't find the identical item node in existing Items xml"));
hr = E_FAIL;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// FindItem()
//
// Input:
// pCatalog - the pointer to the CXmlCatalog object
// hNodeItem - the handle of the <item> node of the catalog xml; we need
// to find the corresponding <itemStatus> node in the existing
// items xml with the identical <identity>, <platform> and
// <client> nodes.
// Output:
// phNodeItem - the handle we pass back to differentiate different
// <itemStatus> node in items xml
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::FindItem(CXmlCatalog* pCatalog,
HANDLE_NODE hNodeItem,
HANDLE_NODE* phNodeItem)
{
LOG_Block("FindItem() by handle");
IXMLDOMNode* pNode = NULL;
if (NULL != (pNode = pCatalog->GetDOMNodebyHandle(hNodeItem)))
{
return FindItem(pNode, phNodeItem, TRUE);
}
LOG_Error(_T("Can't retrieve valid item node from catalog xml"));
return E_FAIL;
}
/*
/////////////////////////////////////////////////////////////////////////////
// IfSameClientInfo()
//
// Return TRUE if the two <client> nodes are identical. Return FALSE otherwise.
/////////////////////////////////////////////////////////////////////////////
BOOL CXmlItems::IfSameClientInfo(IXMLDOMNode* pNodeClient1, IXMLDOMNode* pNodeClient2)
{
LOG_Block("IfSameClientInfo()");
BSTR bstrText1 = NULL, bstrText2 = NULL;
BOOL fResult = FALSE;
GetText(pNodeClient1, &bstrText1);
GetText(pNodeClient2, &bstrText2);
if (NULL != bstrText1 && NULL != bstrText2)
{
fResult = CompareBSTRsEqual(bstrText1, bstrText2);
}
SysFreeString(bstrText1);
SysFreeString(bstrText2);
if (!fResult)
{
LOG_XML(_T("Different <client>\'s found."));
}
else
{
LOG_XML(_T("Same <client>\'s found."));
}
return fResult;
}
/////////////////////////////////////////////////////////////////////////////
// IfSameIdentity()
//
// Return TRUE if the two <identity> nodes are identical. Return FALSE otherwise.
/////////////////////////////////////////////////////////////////////////////
BOOL CXmlItems::IfSameIdentity(IXMLDOMNode* pNodeIdentity1, IXMLDOMNode* pNodeIdentity2)
{
LOG_Block("IfSameIdentity()");
BOOL fResult = FALSE;
BSTR bstrNameGUID = SysAllocString(L"guid");
BSTR bstrNameIDName = SysAllocString(L"name");
BSTR bstrNameIDPublisherName = SysAllocString(L"publisherName");
BSTR bstrNameType = SysAllocString(L"type");
BSTR bstrNameVersion = SysAllocString(L"version");
BSTR bstrNameLanguage = SysAllocString(L"language");
//
// compare <guid> node
//
if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameGUID))
{
goto CleanUp;
}
//
// compare <publisherName> node
//
if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameIDPublisherName))
{
goto CleanUp;
}
//
// compare "name" attribute, this is a required attribute
//
if (!IfHasSameAttribute(pNodeIdentity1, pNodeIdentity2, bstrNameIDName, FALSE))
{
goto CleanUp;
}
//
// compare <type> node
//
if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameType))
{
goto CleanUp;
}
//
// compare <version> node, which really means "file version" here
//
if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameVersion))
{
goto CleanUp;
}
//
// compare <language> node
//
if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameLanguage))
{
goto CleanUp;
}
fResult = TRUE;
CleanUp:
SysFreeString(bstrNameGUID);
SysFreeString(bstrNameIDName);
SysFreeString(bstrNameIDPublisherName);
SysFreeString(bstrNameType);
SysFreeString(bstrNameVersion);
SysFreeString(bstrNameLanguage);
if (!fResult)
{
LOG_XML(_T("Different <identity>\'s found."));
}
else
{
LOG_XML(_T("Same <identity>\'s found."));
}
return fResult;
}
/////////////////////////////////////////////////////////////////////////////
// IfSamePlatform()
//
// Return TRUE if the two <platform> nodes are identical. Return FALSE otherwise.
/////////////////////////////////////////////////////////////////////////////
BOOL CXmlItems::IfSamePlatform(IXMLDOMNode* pNodePlatform1, IXMLDOMNode* pNodePlatform2)
{
LOG_Block("IfSamePlatform()");
HRESULT hr1 = S_OK, hr2 = S_OK;
BSTR bstrPlatform1 = NULL, bstrPlatform2 = NULL;
BOOL fResult = FALSE;
hr1 = pNodePlatform1->get_xml(&bstrPlatform1);
hr2 = pNodePlatform2->get_xml(&bstrPlatform2);
if (FAILED(hr1) || FAILED(hr2) || !CompareBSTRsEqual(bstrPlatform1, bstrPlatform2))
goto CleanUp;
fResult = TRUE;
CleanUp:
SysFreeString(bstrPlatform1);
SysFreeString(bstrPlatform2);
return fResult;
}
*/
/////////////////////////////////////////////////////////////////////////////
// MergeItemDownloaded()
//
// Insert items with download history into existing history (insert in front)
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::MergeItemDownloaded(CXmlItems *pHistoryDownload)
{
LOG_Block("MergeItemDownloaded()");
HRESULT hr = S_OK;
IXMLDOMNode* pNodeItem = NULL;
IXMLDOMNode* pNodeItemNew = NULL;
IXMLDOMNode* pNodeItemRef = NULL;
IXMLDOMNode* pNodeXML = NULL;
BSTR bstrNameSpaceSchema = NULL;
LPTSTR pszItemsSchema = NULL;
LPTSTR pszNameSpaceSchema = NULL;
HANDLE_NODE hNodeItem = HANDLE_NODE_INVALID;
HANDLE_NODELIST hNodeListItem = HANDLE_NODELIST_INVALID;
hNodeListItem = pHistoryDownload->GetFirstItem(&hNodeItem);
if (HANDLE_NODELIST_INVALID != hNodeListItem)
{
//
// if this is the first time writing history
// (e.g. the log file does not exist yet), do
// initialization for m_pDocItems here...
//
if (NULL == m_pDocItems)
{
hr = CoCreateInstance(CLSID_DOMDocument,
NULL,
CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument,
(void **) &m_pDocItems);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
else
{
//
// create the <?xml version="1.0"?> node
//
pNodeXML = CreateDOMNode(m_pDocItems, NODE_PROCESSING_INSTRUCTION, KEY_XML);
if (NULL == pNodeXML) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, pNodeXML));
//
// process the iuident.txt to find the Items schema path
//
TCHAR szIUDir[MAX_PATH];
TCHAR szIdentFile[MAX_PATH];
pszItemsSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
if (NULL == pszItemsSchema)
{
hr = E_OUTOFMEMORY;
LOG_ErrorMsg(hr);
goto CleanUp;
}
pszNameSpaceSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
if (NULL == pszNameSpaceSchema)
{
hr = E_OUTOFMEMORY;
LOG_ErrorMsg(hr);
goto CleanUp;
}
GetIndustryUpdateDirectory(szIUDir);
hr = PathCchCombine(szIdentFile, ARRAYSIZE(szIdentFile), szIUDir, IDENTTXT);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
GetPrivateProfileString(IDENT_IUSCHEMA,
IDENT_IUSCHEMA_ITEMS,
_T(""),
pszItemsSchema,
INTERNET_MAX_URL_LENGTH,
szIdentFile);
if ('\0' == pszItemsSchema[0])
{
// no Items schema path specified in iuident.txt
LOG_Error(_T("No schema path specified in iuident.txt for Items"));
goto CleanUp;
}
hr = StringCchPrintfEx(pszNameSpaceSchema, INTERNET_MAX_URL_LENGTH, NULL, NULL, MISTSAFE_STRING_FLAGS,
_T("x-schema:%s"), pszItemsSchema);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
bstrNameSpaceSchema = T2BSTR(pszNameSpaceSchema);
//
// create the <items> node with the path of the schema
//
m_pNodeItems = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_ITEMS, bstrNameSpaceSchema);
if (NULL == m_pNodeItems) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, m_pNodeItems));
}
}
else
{
SafeReleaseNULL(m_pNodeItems);
FindSingleDOMNode(m_pDocItems, KEY_ITEMS, &m_pNodeItems);
}
if (NULL != m_pNodeItems)
{
if (NULL != (pNodeItem = pHistoryDownload->GetDOMNodebyHandle(hNodeItem)))
{
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew));
CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef));
// SafeReleaseNULL(pNodeItem);
SafeReleaseNULL(pNodeItemNew);
SafeReleaseNULL(pNodeItemRef);
}
while (SUCCEEDED(pHistoryDownload->GetNextItem(hNodeListItem, &hNodeItem)))
{
if (NULL != (pNodeItem = pHistoryDownload->GetDOMNodebyHandle(hNodeItem)))
{
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew));
CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef));
// SafeReleaseNULL(pNodeItem);
SafeReleaseNULL(pNodeItemNew);
SafeReleaseNULL(pNodeItemRef);
}
}
}
}
CleanUp:
pHistoryDownload->CloseItemList(hNodeListItem);
// SafeReleaseNULL(pNodeItem);
SafeReleaseNULL(pNodeItemNew);
SafeReleaseNULL(pNodeItemRef);
SafeReleaseNULL(pNodeXML);
SysFreeString(bstrNameSpaceSchema);
SafeHeapFree(pszItemsSchema);
SafeHeapFree(pszNameSpaceSchema);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// UpdateItemInstalled()
//
// Update items with installation history in existing history
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::UpdateItemInstalled(CXmlItems *pHistoryInstall)
{
LOG_Block("UpdateItemInstalled()");
USES_IU_CONVERSION;
HRESULT hr = S_OK;
IXMLDOMNode* pNodeItem = NULL;
IXMLDOMNode* pNodeItemNew = NULL;
IXMLDOMNode* pNodeItemRef = NULL;
IXMLDOMNode* pNodeItemExist = NULL;
IXMLDOMNode* pNodeInstall = NULL;
IXMLDOMNode* pNodeInstallExist = NULL;
IXMLDOMNode* pNodeInstallNew = NULL;
IXMLDOMNode* pNodeInstallOut = NULL;
IXMLDOMNode* pNodeXML = NULL;
BSTR bstrInstallStatusExist = NULL;
BSTR bstrInstallStatusNew = NULL;
BSTR bstrTimeStamp = NULL;
BSTR bstrNameSpaceSchema = NULL;
LPTSTR pszItemsSchema = NULL;
LPTSTR pszNameSpaceSchema = NULL;
HANDLE_NODE hNodeItem = HANDLE_NODE_INVALID;
HANDLE_NODE hNodeItemExist = HANDLE_NODE_INVALID;
HANDLE_NODELIST hNodeListItem = HANDLE_NODELIST_INVALID;
hNodeListItem = pHistoryInstall->GetFirstItem(&hNodeItem);
if (HANDLE_NODELIST_INVALID != hNodeListItem)
{
//
// if this is the first time writing history
// (e.g. the log file does not exist yet), do
// initialization for m_pDocItems here...
//
if (NULL == m_pDocItems)
{
hr = CoCreateInstance(CLSID_DOMDocument,
NULL,
CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument,
(void **) &m_pDocItems);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
else
{
//
// create the <?xml version="1.0"?> node
//
pNodeXML = CreateDOMNode(m_pDocItems, NODE_PROCESSING_INSTRUCTION, KEY_XML);
if (NULL == pNodeXML) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, pNodeXML));
//
// process the iuident.txt to find the Items schema path
//
TCHAR szIUDir[MAX_PATH];
TCHAR szIdentFile[MAX_PATH];
pszItemsSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
if (NULL == pszItemsSchema)
{
hr = E_OUTOFMEMORY;
LOG_ErrorMsg(hr);
goto CleanUp;
}
pszNameSpaceSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
if (NULL == pszNameSpaceSchema)
{
hr = E_OUTOFMEMORY;
LOG_ErrorMsg(hr);
goto CleanUp;
}
GetIndustryUpdateDirectory(szIUDir);
hr = PathCchCombine(szIdentFile, ARRAYSIZE(szIdentFile), szIUDir, IDENTTXT);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
GetPrivateProfileString(IDENT_IUSCHEMA,
IDENT_IUSCHEMA_ITEMS,
_T(""),
pszItemsSchema,
INTERNET_MAX_URL_LENGTH,
szIdentFile);
if ('\0' == pszItemsSchema[0])
{
// no Items schema path specified in iuident.txt
LOG_Error(_T("No schema path specified in iuident.txt for Items"));
goto CleanUp;
}
hr = StringCchPrintfEx(pszNameSpaceSchema, INTERNET_MAX_URL_LENGTH, NULL, NULL, MISTSAFE_STRING_FLAGS,
_T("x-schema:%s"), pszItemsSchema);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
bstrNameSpaceSchema = T2BSTR(pszNameSpaceSchema);
//
// create the <items> node with the path of the schema
//
m_pNodeItems = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_ITEMS, bstrNameSpaceSchema);
if (NULL == m_pNodeItems) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, m_pNodeItems));
}
}
else
{
SafeReleaseNULL(m_pNodeItems);
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_pDocItems, KEY_ITEMS, &m_pNodeItems));
}
if (NULL != (pNodeItem = pHistoryInstall->GetDOMNodebyHandle(hNodeItem)))
{
if (SUCCEEDED(FindItem(pNodeItem, &hNodeItemExist)))
{
//
// successfully found the match
//
if (NULL != (pNodeItemExist = GetDOMNodebyHandle(hNodeItemExist)))
{
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_INSTALLSTATUS, &pNodeInstall));
FindSingleDOMNode(pNodeItemExist, KEY_INSTALLSTATUS, &pNodeInstallExist);
if (NULL != pNodeInstallExist)
{
//
// found the item already with installStatus; now find out if we want to update
// or append the installStatus
//
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstallExist, KEY_VALUE, &bstrInstallStatusExist));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstall, KEY_VALUE, &bstrInstallStatusNew));
if (CSTR_EQUAL == WUCompareStringI(OLE2T(bstrInstallStatusExist), _T("IN_PROGRESS")) &&
CSTR_EQUAL != WUCompareStringI(OLE2T(bstrInstallStatusNew), _T("IN_PROGRESS")))
{
//
// this entry is an exclusive item with "IN_PROGRESS" installStatus and we found its
// updated installStatus, we need to update its installStatus
//
LOG_Out(_T("Update the exclusive item's installStatus"));
CleanUpIfFailedAndSetHrMsg(pNodeItemExist->removeChild(pNodeInstallExist, &pNodeInstallOut));
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeInstall, m_pDocItems, &pNodeInstallNew));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeItemExist, pNodeInstallNew));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp));
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeItemExist, KEY_TIMESTAMP, bstrTimeStamp));
SafeSysFreeString(bstrTimeStamp);
}
else
{
//
// in this case we append a copy of this item with the new installStatus, since
// this comes from a separate install operation
//
LOG_Out(_T("This item was installed again, add an entry of this item into history \
for the new installation status only."));
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew));
CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef));
}
SafeSysFreeString(bstrInstallStatusExist);
SafeSysFreeString(bstrInstallStatusNew);
}
else
{
//
// found the item without installStatus, update the entry with the installStatus
// and update the timeStamp with its installation timeStamp
//
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeInstall, m_pDocItems, &pNodeInstallNew));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeItemExist, pNodeInstallNew));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp));
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeItemExist, KEY_TIMESTAMP, bstrTimeStamp));
SafeSysFreeString(bstrTimeStamp);
}
}
}
else
{
//
// no match found, this item was not downloaded through IU,
// append this item with the install status
//
LOG_Out(_T("Can't find the downloaded item in existing history. This item was not downloaded \
through IU. Add the item into history for installation status only."));
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew));
CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef));
}
// SafeReleaseNULL(pNodeItem);
// SafeReleaseNULL(pNodeItemExist);
SafeReleaseNULL(pNodeItemNew);
SafeReleaseNULL(pNodeItemRef);
SafeReleaseNULL(pNodeInstall);
SafeReleaseNULL(pNodeInstallExist);
SafeReleaseNULL(pNodeInstallNew);
SafeReleaseNULL(pNodeInstallOut);
}
while (SUCCEEDED(pHistoryInstall->GetNextItem(hNodeListItem, &hNodeItem)))
{
if (NULL != (pNodeItem = pHistoryInstall->GetDOMNodebyHandle(hNodeItem)))
{
if (SUCCEEDED(FindItem(pNodeItem, &hNodeItemExist)))
{
//
// successfully found the match
//
if (NULL != (pNodeItemExist = GetDOMNodebyHandle(hNodeItemExist)))
{
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_INSTALLSTATUS, &pNodeInstall));
FindSingleDOMNode(pNodeItemExist, KEY_INSTALLSTATUS, &pNodeInstallExist);
if (NULL != pNodeInstallExist)
{
//
// found the item already with installStatus; now find out if we want to update
// or append the installStatus
//
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstallExist, KEY_VALUE, &bstrInstallStatusExist));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstall, KEY_VALUE, &bstrInstallStatusNew));
if (CSTR_EQUAL == WUCompareStringI(OLE2T(bstrInstallStatusExist), _T("IN_PROGRESS")) &&
CSTR_EQUAL != WUCompareStringI(OLE2T(bstrInstallStatusNew), _T("IN_PROGRESS")))
{
//
// this entry is an exclusive item with "IN_PROGRESS" installStatus and we found its
// updated installStatus, we need to update its installStatus
//
LOG_Out(_T("Update the exclusive item's installStatus"));
CleanUpIfFailedAndSetHrMsg(pNodeItemExist->removeChild(pNodeInstallExist, &pNodeInstallOut));
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeInstall, m_pDocItems, &pNodeInstallNew));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeItemExist, pNodeInstallNew));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp));
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeItemExist, KEY_TIMESTAMP, bstrTimeStamp));
SafeSysFreeString(bstrTimeStamp);
}
else
{
//
// in this case we append a copy of this item with the new installStatus, since
// this comes from a separate install operation
//
LOG_Out(_T("This item was installed again, add an entry of this item into history \
for the new installation status only."));
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew));
CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef));
}
SafeSysFreeString(bstrInstallStatusExist);
SafeSysFreeString(bstrInstallStatusNew);
}
else
{
//
// found the item without installStatus, update the entry with the installStatus
// and update the timeStamp with its installation timeStamp
//
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeInstall, m_pDocItems, &pNodeInstallNew));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeItemExist, pNodeInstallNew));
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp));
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeItemExist, KEY_TIMESTAMP, bstrTimeStamp));
SafeSysFreeString(bstrTimeStamp);
}
}
}
else
{
//
// no match found, this item was not downloaded through IU,
// append this item with the install status
//
LOG_Out(_T("Can't find the downloaded item in existing history. This item was not downloaded \
through IU. Add the item into history for installation status only."));
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew));
CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef));
}
// SafeReleaseNULL(pNodeItem);
// SafeReleaseNULL(pNodeItemExist);
SafeReleaseNULL(pNodeItemNew);
SafeReleaseNULL(pNodeItemRef);
SafeReleaseNULL(pNodeInstall);
SafeReleaseNULL(pNodeInstallExist);
SafeReleaseNULL(pNodeInstallNew);
SafeReleaseNULL(pNodeInstallOut);
}
}
}
CleanUp:
pHistoryInstall->CloseItemList(hNodeListItem);
// SafeReleaseNULL(pNodeItem);
// SafeReleaseNULL(pNodeItemExist);
SafeReleaseNULL(pNodeItemNew);
SafeReleaseNULL(pNodeItemRef);
SafeReleaseNULL(pNodeInstall);
SafeReleaseNULL(pNodeInstallExist);
SafeReleaseNULL(pNodeInstallNew);
SafeReleaseNULL(pNodeInstallOut);
SafeReleaseNULL(pNodeXML);
SysFreeString(bstrInstallStatusExist);
SysFreeString(bstrInstallStatusNew);
SysFreeString(bstrTimeStamp);
SysFreeString(bstrNameSpaceSchema);
SafeHeapFree(pszItemsSchema);
SafeHeapFree(pszNameSpaceSchema);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// UpdateItemInstallStatus()
//
// Update the install status of the given item
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::UpdateItemInstallStatus(HANDLE_NODE hNodeItem,
BSTR bstrValue,
INT iNeedsReboot /*= -1*/,
DWORD dwErrorCode /*= 0*/)
{
LOG_Block("UpdateItemInstallStatus()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeInstallStatus = NULL;
//
// get the <installStatus> node
//
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_INSTALLSTATUS, &pNodeInstallStatus));
//
// set the "value" attribute
//
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_VALUE, bstrValue));
//
// set the "needsReboot" attribute
//
if (-1 != iNeedsReboot)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_NEEDSREBOOT, iNeedsReboot));
}
//
// set the "errorCode" attribute
//
if (0 != dwErrorCode)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_ERRORCODE, dwErrorCode));
}
CleanUp:
SafeReleaseNULL(pNodeInstallStatus);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddItem()
//
// Input:
// pNodeItem - the <item> node of the catalog xml; we need to read
// <identity> node, <description> node and <platform> nodes
// from it and write to the items xml.
// Output:
// phNodeItem - the handle we pass back to differentiate different
// <itemStatus> node in items xml
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::AddItem(IXMLDOMNode* pNodeItem, HANDLE_NODE* phNodeItem)
{
LOG_Block("AddItem()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeIndentity = NULL;
IXMLDOMNode* pNodeIndentityNew = NULL;
IXMLDOMNode* pNodeDescription = NULL;
IXMLDOMNode* pNodeDescriptionNew = NULL;
IXMLDOMNode* pNodePlatform = NULL;
IXMLDOMNode* pNodePlatformNew = NULL;
HANDLE_NODELIST hNodeList = HANDLE_NODELIST_INVALID;
*phNodeItem = CreateDOMNodeWithHandle(m_pDocItems, NODE_ELEMENT, KEY_ITEMSTATUS);
if (HANDLE_NODE_INVALID == *phNodeItem) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, m_ppNodeArray[*phNodeItem]));
hNodeList = FindFirstDOMNode(pNodeItem, KEY_IDENTITY, &pNodeIndentity);
if (HANDLE_NODELIST_INVALID != hNodeList)
{
SafeFindCloseHandle(hNodeList);
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeIndentity, m_pDocItems, &pNodeIndentityNew));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[*phNodeItem], pNodeIndentityNew));
}
hNodeList = FindFirstDOMNode(pNodeItem, KEY_DESCRIPTION, &pNodeDescription);
if (HANDLE_NODELIST_INVALID != hNodeList)
{
SafeFindCloseHandle(hNodeList);
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeDescription, m_pDocItems, &pNodeDescriptionNew));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[*phNodeItem], pNodeDescriptionNew));
}
hNodeList = FindFirstDOMNode(pNodeItem, KEY_PLATFORM, &pNodePlatform);
if (HANDLE_NODELIST_INVALID != hNodeList)
{
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodePlatform, m_pDocItems, &pNodePlatformNew));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[*phNodeItem], pNodePlatformNew));
SafeReleaseNULL(pNodePlatform);
SafeReleaseNULL(pNodePlatformNew);
while (SUCCEEDED(FindNextDOMNode(hNodeList, &pNodePlatform)))
{
CleanUpIfFailedAndSetHrMsg(CopyNode(pNodePlatform, m_pDocItems, &pNodePlatformNew));
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[*phNodeItem], pNodePlatformNew));
SafeReleaseNULL(pNodePlatform);
SafeReleaseNULL(pNodePlatformNew);
}
}
CleanUp:
if (HANDLE_NODELIST_INVALID != hNodeList)
{
SafeFindCloseHandle(hNodeList);
}
SafeReleaseNULL(pNodeIndentity);
SafeReleaseNULL(pNodeIndentityNew);
SafeReleaseNULL(pNodeDescription);
SafeReleaseNULL(pNodeDescriptionNew);
SafeReleaseNULL(pNodePlatform);
SafeReleaseNULL(pNodePlatformNew);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddItem()
//
// Input:
// pCatalog - the pointer to the CXmlCatalog object
// hNodeItem - the handle of the <item> node of the catalog xml; we need
// to read <identity> node, <description> node and <platform>
// nodes from it and write to the items xml.
// Output:
// phNodeItem - the handle we pass back to differentiate different
// <itemStatus> node in items xml
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::AddItem(CXmlCatalog* pCatalog, HANDLE_NODE hNodeItem, HANDLE_NODE* phNodeItem)
{
LOG_Block("AddItem() by handle");
IXMLDOMNode* pNode = NULL;
if (NULL != (pNode = pCatalog->GetDOMNodebyHandle(hNodeItem)))
{
return AddItem(pNode, phNodeItem);
}
LOG_Error(_T("Can't retrieve valid item node from catalog xml"));
return E_FAIL;
}
/////////////////////////////////////////////////////////////////////////////
// AddTimeStamp()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::AddTimeStamp(HANDLE_NODE hNodeItem)
{
LOG_Block("AddTimeStamp()");
USES_IU_CONVERSION;
HRESULT hr = E_FAIL;
TCHAR szTimestamp[32];
SYSTEMTIME stTimestamp;
BSTR bstrTimeStamp = NULL;
GetLocalTime(&stTimestamp);
hr = StringCchPrintfEx(szTimestamp, ARRAYSIZE(szTimestamp), NULL, NULL, MISTSAFE_STRING_FLAGS,
_T("%4d-%02d-%02dT%02d:%02d:%02d"), // "ISO 8601" format for "datatime" datatype in xml
stTimestamp.wYear,
stTimestamp.wMonth,
stTimestamp.wDay,
stTimestamp.wHour,
stTimestamp.wMinute,
stTimestamp.wSecond);
CleanUpIfFailedAndSetHrMsg(hr);
bstrTimeStamp = SysAllocString(T2OLE(szTimestamp));
//
// set the "timestamp" attribute
//
CleanUpIfFailedAndSetHrMsg(SetAttribute(m_ppNodeArray[hNodeItem], KEY_TIMESTAMP, bstrTimeStamp));
CleanUp:
SysFreeString(bstrTimeStamp);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddDetectResult()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::AddDetectResult(HANDLE_NODE hNodeItem,
INT iInstalled /*= -1*/,
INT iUpToDate /*= -1*/,
INT iNewerVersion /*= -1*/,
INT iExcluded /*= -1*/,
INT iForce /*= -1*/,
INT iComputerSystem /* = -1 */)
{
LOG_Block("AddDetectResult()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeDetectResult = NULL;
//
// create the <detectResult> node
//
pNodeDetectResult = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_DETECTRESULT);
if (NULL == pNodeDetectResult) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeItem], pNodeDetectResult));
//
// set the "installed" attribute
//
if (-1 != iInstalled)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_INSTALLED, iInstalled));
}
//
// set the "upToDate" attribute
//
if (-1 != iUpToDate)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_UPTODATE, iUpToDate));
}
//
// set the "newerVersion" attribute
//
if (-1 != iNewerVersion)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_NEWERVERSION, iNewerVersion));
}
//
// set the "excluded" attribute
//
if (-1 != iExcluded)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_EXCLUDED, iExcluded));
}
//
// set the "force" attribute
//
if (-1 != iForce)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_FORCE, iForce));
}
//
// set computerSystem attribute
//
if (-1 != iComputerSystem)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_COMPUTERSYSTEM, iComputerSystem));
}
CleanUp:
SafeReleaseNULL(pNodeDetectResult);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddDownloadStatus()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::AddDownloadStatus(HANDLE_NODE hNodeItem, BSTR bstrValue, DWORD dwErrorCode /*= 0*/)
{
LOG_Block("AddDownloadStatus()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeDownloadStatus = NULL;
//
// create the <downloadStatus> node
//
pNodeDownloadStatus = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_DOWNLOADSTATUS);
if (NULL == pNodeDownloadStatus) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeItem], pNodeDownloadStatus));
//
// set the "value" attribute
//
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDownloadStatus, KEY_VALUE, bstrValue));
//
// set the "errorCode" attribute
//
if (0 != dwErrorCode)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDownloadStatus, KEY_ERRORCODE, dwErrorCode));
}
CleanUp:
SafeReleaseNULL(pNodeDownloadStatus);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddDownloadPath()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::AddDownloadPath(HANDLE_NODE hNodeItem, BSTR bstrDownloadPath)
{
LOG_Block("AddDownloadPath()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeDownloadPath = NULL;
IXMLDOMNode* pNodeDownloadPathText = NULL;
pNodeDownloadPath = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_DOWNLOADPATH);
if (NULL == pNodeDownloadPath) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeItem], pNodeDownloadPath));
pNodeDownloadPathText = CreateDOMNode(m_pDocItems, NODE_TEXT, NULL);
if (NULL == pNodeDownloadPathText) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(SetValue(pNodeDownloadPathText, bstrDownloadPath));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeDownloadPath, pNodeDownloadPathText));
CleanUp:
SafeReleaseNULL(pNodeDownloadPath);
SafeReleaseNULL(pNodeDownloadPathText);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddInstallStatus()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::AddInstallStatus(HANDLE_NODE hNodeItem,
BSTR bstrValue,
BOOL fNeedsReboot,
DWORD dwErrorCode /*= 0*/)
{
LOG_Block("AddInstallStatus()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeInstallStatus = NULL;
//
// create the <installStatus> node
//
pNodeInstallStatus = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_INSTALLSTATUS);
if (NULL == pNodeInstallStatus) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeItem], pNodeInstallStatus));
//
// set the "value" attribute
//
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_VALUE, bstrValue));
//
// set the "needsReboot" attribute
//
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_NEEDSREBOOT, fNeedsReboot));
//
// set the "errorCode" attribute
//
if (0 != dwErrorCode)
{
CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_ERRORCODE, dwErrorCode));
}
CleanUp:
SafeReleaseNULL(pNodeInstallStatus);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// AddClientInfo()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::AddClientInfo(HANDLE_NODE hNodeItem, BSTR bstrClient)
{
LOG_Block("AddClientInfo()");
HRESULT hr = E_FAIL;
IXMLDOMNode* pNodeClient = NULL;
IXMLDOMNode* pNodeClientText = NULL;
pNodeClient = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_CLIENT);
if (NULL == pNodeClient) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeItem], pNodeClient));
pNodeClientText = CreateDOMNode(m_pDocItems, NODE_TEXT, NULL);
if (NULL == pNodeClientText) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(SetValue(pNodeClientText, bstrClient));
CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeClient, pNodeClientText));
CleanUp:
SafeReleaseNULL(pNodeClient);
SafeReleaseNULL(pNodeClientText);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// MigrateV3History()
//
// Migrate V3 History: Consumer history only.
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::MigrateV3History(LPCTSTR pszHistoryFilePath)
{
LOG_Block("MigrateV3History()");
HRESULT hr = S_OK;
IXMLDOMNode* pNodeXML = NULL;
IXMLDOMNode* pNodeItemStatus = NULL;
IXMLDOMNode* pNodeIdentity = NULL;
IXMLDOMNode* pNodeDescription = NULL;
IXMLDOMNode* pNodeDescriptionText = NULL;
IXMLDOMNode* pNodeTitle = NULL;
IXMLDOMNode* pNodeTitleText = NULL;
IXMLDOMNode* pNodeVersion = NULL;
IXMLDOMNode* pNodeVersionText = NULL;
IXMLDOMNode* pNodeInstallStatus = NULL;
IXMLDOMNode* pNodeClient = NULL;
IXMLDOMNode* pNodeClientText = NULL;
BSTR bstrNameSpaceSchema = NULL, bstrStatus = NULL, bstrString = NULL;
LPTSTR pszItemsSchema = NULL;
LPTSTR pszNameSpaceSchema = NULL;
CV3AppLog V3History(pszHistoryFilePath);
char szLineType[32];
char szTemp[32];
char szDate[32];
char szTime[32];
char szPUID[32]; // puid - migrate to <identity "name">
char szTitle[256]; // title - migrate to <description>-><descriptionText>-><title>
char szVersion[40]; // version - migrate to <identity>-><version>
char szTimeStamp[32]; // timestamp - migrate to <itemStatus "timestamp">
char szResult[16]; // result - migrate to <installStatus "value">
char szErrCode[16]; // errorcode - migrate to <installStatus "errorCode">
USES_IU_CONVERSION;
V3History.StartReading();
while (V3History.ReadLine())
{
SafeSysFreeString(bstrString);
// get line type (first field)
V3History.CopyNextField(szLineType, ARRAYSIZE(szLineType));
if ((_stricmp(szLineType, LOG_V3CAT) == 0) || (_stricmp(szLineType, LOG_V3_2) == 0))
{
// get "puid" field
V3History.CopyNextField(szPUID, ARRAYSIZE(szPUID));
// get "operation" field: installed/uninstalled
// we only migrate installed item
V3History.CopyNextField(szTemp, ARRAYSIZE(szTemp));
if (0 != _stricmp(szTemp, LOG_INSTALL))
continue;
//
// now we start to create <itemStatus> node for this item
//
if (NULL == m_pDocItems)
{
//
// we don't have IU history file yet
//
hr = CoCreateInstance(CLSID_DOMDocument,
NULL,
CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument,
(void **) &m_pDocItems);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
else
{
//
// create the <?xml version="1.0"?> node
//
pNodeXML = CreateDOMNode(m_pDocItems, NODE_PROCESSING_INSTRUCTION, KEY_XML);
if (NULL == pNodeXML) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, pNodeXML));
//
// process the iuident.txt to find the Items schema path
//
TCHAR szIUDir[MAX_PATH];
TCHAR szIdentFile[MAX_PATH];
pszItemsSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
if (NULL == pszItemsSchema)
{
hr = E_OUTOFMEMORY;
LOG_ErrorMsg(hr);
goto CleanUp;
}
pszNameSpaceSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
if (NULL == pszNameSpaceSchema)
{
hr = E_OUTOFMEMORY;
LOG_ErrorMsg(hr);
goto CleanUp;
}
GetIndustryUpdateDirectory(szIUDir);
hr = PathCchCombine(szIdentFile, ARRAYSIZE(szIdentFile), szIUDir, IDENTTXT);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
GetPrivateProfileString(IDENT_IUSCHEMA,
IDENT_IUSCHEMA_ITEMS,
_T(""),
pszItemsSchema,
INTERNET_MAX_URL_LENGTH,
szIdentFile);
if ('\0' == pszItemsSchema[0])
{
// no Items schema path specified in iuident.txt
LOG_Error(_T("No schema path specified in iuident.txt for Items"));
goto CleanUp;
}
hr = StringCchPrintfEx(pszNameSpaceSchema, INTERNET_MAX_URL_LENGTH, NULL, NULL, MISTSAFE_STRING_FLAGS,
_T("x-schema:%s"), pszItemsSchema);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
goto CleanUp;
}
bstrNameSpaceSchema = T2BSTR(pszNameSpaceSchema);
//
// create the <items> node with the path of the schema
//
m_pNodeItems = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_ITEMS, bstrNameSpaceSchema);
if (NULL == m_pNodeItems) goto CleanUp;
CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, m_pNodeItems));
}
}
else
{
SafeReleaseNULL(m_pNodeItems);
FindSingleDOMNode(m_pDocItems, KEY_ITEMS, &m_pNodeItems);
}
// create <itemStatus> node
pNodeItemStatus = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_ITEMSTATUS);
if (NULL == pNodeItemStatus) continue;
SkipIfFail(InsertNode(m_pNodeItems, pNodeItemStatus));
// create <client> node
pNodeClient = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_CLIENT);
if (NULL == pNodeClient) continue;
pNodeClientText = CreateDOMNode(m_pDocItems, NODE_TEXT, NULL);
if (NULL == pNodeClientText) continue;
BSTR bstrV3Client = SysAllocString(C_V3_CLIENTINFO);
SkipIfFail(SetValue(pNodeClientText, bstrV3Client));
SkipIfFail(InsertNode(pNodeClient, pNodeClientText));
SkipIfFail(InsertNode(pNodeItemStatus, pNodeClient));
SafeSysFreeString(bstrV3Client);
// create <identity> node
pNodeIdentity = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_IDENTITY);
if (NULL == pNodeIdentity) continue;
SkipIfFail(InsertNode(pNodeItemStatus, pNodeIdentity));
// set the "name" attribute for <identity>
bstrString = SysAllocString(A2OLE(szPUID));
SkipIfFail(SetAttribute(pNodeIdentity, KEY_NAME, bstrString));
// set the "itemID" attribute for <identity>
SkipIfFail(SetAttribute(pNodeIdentity, KEY_ITEMID, bstrString));
SafeSysFreeString(bstrString);
// get "title" field
V3History.CopyNextField(szTitle, ARRAYSIZE(szTitle));
// create <description> node
pNodeDescription = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_DESCRIPTION);
if (NULL == pNodeDescription) continue;
SkipIfFail(SetAttribute(pNodeDescription, KEY_HIDDEN, 0));
SkipIfFail(InsertNode(pNodeItemStatus, pNodeDescription));
// create <descriptionText> node
pNodeDescriptionText = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_DESCRIPTIONTEXT);
if (NULL == pNodeDescriptionText) continue;
SkipIfFail(InsertNode(pNodeDescription, pNodeDescriptionText));
// create <title> node
pNodeTitle = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_TITLE);
if (NULL == pNodeTitle) continue;
pNodeTitleText = CreateDOMNode(m_pDocItems, NODE_TEXT, NULL);
if (NULL == pNodeTitleText) continue;
bstrString = SysAllocString(A2OLE(szTitle));
SkipIfFail(SetValue(pNodeTitleText, bstrString));
SkipIfFail(InsertNode(pNodeTitle, pNodeTitleText));
SkipIfFail(InsertNode(pNodeDescriptionText, pNodeTitle));
SafeSysFreeString(bstrString);
// get "version" field
V3History.CopyNextField(szVersion, ARRAYSIZE(szVersion));
// create <version> node
pNodeVersion = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_VERSION);
if (NULL == pNodeVersion) continue;
pNodeVersionText = CreateDOMNode(m_pDocItems, NODE_TEXT, NULL);
if (NULL == pNodeVersionText) continue;
bstrString = SysAllocString(A2OLE(szVersion));
SkipIfFail(SetValue(pNodeVersionText, bstrString));
SkipIfFail(InsertNode(pNodeVersion, pNodeVersionText));
SkipIfFail(InsertNode(pNodeIdentity, pNodeVersion));
SafeSysFreeString(bstrString);
// get timestamp
if ((_stricmp(szLineType, LOG_V3_2) == 0))
{
// read the timestamp and convert to "ISO 8601" format for "datatime" datatype in xml:
// for example, 2001-05-01T18:30:00
// so we only need to replace the space with 'T'
// timestamp
V3History.CopyNextField(szTimeStamp, ARRAYSIZE(szTimeStamp));
char *p = strchr(szTimeStamp, ' ');
if (NULL != p) // if (NULL == p): there's no space then leave it as is to pass into SetAttribute
{
*p = 'T';
}
}
else
{
// V3 Beta had two fields for date and time, we need read both these fields:
// date
V3History.CopyNextField(szDate, ARRAYSIZE(szDate));
// time
V3History.CopyNextField(szTime, ARRAYSIZE(szTime));
hr = StringCchPrintfExA(szTimeStamp, ARRAYSIZE(szTimeStamp), NULL, NULL, MISTSAFE_STRING_FLAGS,
"%sT%s", szDate, szTime);
SkipIfFail(hr);
}
// set the "timestamp" attribute for <itemStatus>
bstrString = SysAllocString(A2OLE(szTimeStamp));
SkipIfFail(SetAttribute(pNodeItemStatus, KEY_TIMESTAMP, bstrString));
SafeSysFreeString(bstrString);
// skip the "record type" field
V3History.CopyNextField(szTemp, ARRAYSIZE(szTemp));
// get "result" field
V3History.CopyNextField(szResult, ARRAYSIZE(szResult));
// create <InstallStatus> node
pNodeInstallStatus = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_INSTALLSTATUS);
if (NULL == pNodeInstallStatus) continue;
SkipIfFail(InsertNode(pNodeItemStatus, pNodeInstallStatus));
// set the "value" attribute for <installStatus>
if (_stricmp(szResult, LOG_SUCCESS) == 0)
{
bstrStatus = SysAllocString(L"COMPLETE");
}
else if (_stricmp(szTemp, LOG_STARTED) == 0)
{
bstrStatus = SysAllocString(L"IN_PROGRESS");
}
else
{
bstrStatus = SysAllocString(L"FAILED");
}
SkipIfFail(SetAttribute(pNodeInstallStatus, KEY_VALUE, bstrStatus));
if (_stricmp(szResult, LOG_SUCCESS) != 0)
{
// get "error code" field
V3History.CopyNextField(szErrCode, ARRAYSIZE(szErrCode));
// set the "errorCode" attribute for <installStatus>
SkipIfFail(SetAttribute(pNodeInstallStatus, KEY_ERRORCODE, atoh(szErrCode)));
}
}
}
V3History.StopReading();
CleanUp:
SafeReleaseNULL(pNodeXML);
SafeReleaseNULL(pNodeItemStatus);
SafeReleaseNULL(pNodeIdentity);
SafeReleaseNULL(pNodeDescriptionText);
SafeReleaseNULL(pNodeTitle);
SafeReleaseNULL(pNodeTitleText);
SafeReleaseNULL(pNodeVersion);
SafeReleaseNULL(pNodeVersionText);
SafeReleaseNULL(pNodeInstallStatus);
SafeReleaseNULL(pNodeClient);
SafeReleaseNULL(pNodeClientText);
SysFreeString(bstrString);
SysFreeString(bstrNameSpaceSchema);
SysFreeString(bstrStatus);
SafeHeapFree(pszItemsSchema);
SafeHeapFree(pszNameSpaceSchema);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetItemsBSTR()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::GetItemsBSTR(BSTR *pbstrXmlItems)
{
LOG_Block("GetItemsBSTR()");
if (NULL == m_pDocItems)
{
*pbstrXmlItems = NULL;
return S_OK;
}
//
// convert XML DOC into BSTR
//
HRESULT hr = m_pDocItems->get_xml(pbstrXmlItems);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// GetFilteredHistoryBSTR()
/////////////////////////////////////////////////////////////////////////////
HRESULT CXmlItems::GetFilteredHistoryBSTR(BSTR bstrBeginDateTime,
BSTR bstrEndDateTime,
BSTR bstrClient,
BSTR *pbstrXmlHistory)
{
LOG_Block("GetFilteredHistoryBSTR()");
USES_IU_CONVERSION;
HRESULT hr = S_OK;
IXMLDOMNode* pNodeItems = NULL;
IXMLDOMNode* pNodeItem = NULL;
IXMLDOMNode* pNodeItemOut = NULL;
IXMLDOMNode* pNodeClient = NULL;
BSTR bstrTimeStamp = NULL;
BSTR bstrClientInfo = NULL;
BOOL fOutOfRange = FALSE;
HANDLE_NODELIST hNodeList = HANDLE_NODELIST_INVALID;
if (NULL == pbstrXmlHistory)
{
SetHrMsgAndGotoCleanUp(E_INVALIDARG);
}
if (NULL != m_pDocItems)
{
if (SUCCEEDED(FindSingleDOMNode(m_pDocItems, KEY_ITEMS, &pNodeItems)))
{
hNodeList = FindFirstDOMNode(pNodeItems, KEY_ITEMSTATUS, &pNodeItem);
if (HANDLE_NODELIST_INVALID != hNodeList)
{
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp));
if (NULL != bstrTimeStamp)
{
if ((NULL != bstrBeginDateTime) && (0 != SysStringLen(bstrBeginDateTime)) &&
(CompareBSTRs(bstrTimeStamp, bstrBeginDateTime) < 0))
{
//
// remove the item whose timestamp is out of range;
// set the flag to ignore the timestamp comparison for the rest of nodes
//
CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut));
fOutOfRange = TRUE;
}
else if ((NULL != bstrEndDateTime) && (0 != SysStringLen(bstrEndDateTime)) &&
(CompareBSTRs(bstrTimeStamp, bstrEndDateTime) > 0))
{
//
// remove the item whose timestamp is out of range
//
CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut));
}
else
{
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_CLIENT, &pNodeClient));
CleanUpIfFailedAndSetHrMsg(GetText(pNodeClient, &bstrClientInfo));
if ((NULL != bstrClient) && (0 != SysStringLen(bstrClient)) &&
(WUCompareStringI(OLE2T(bstrClientInfo), OLE2T(bstrClient)) != CSTR_EQUAL))
{
//
// remove the item whose clieninfo does not match what we need
//
CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut));
}
}
}
SafeReleaseNULL(pNodeItem);
SafeReleaseNULL(pNodeItemOut);
SafeReleaseNULL(pNodeClient);
SafeSysFreeString(bstrTimeStamp);
SafeSysFreeString(bstrClientInfo);
while (SUCCEEDED(FindNextDOMNode(hNodeList, &pNodeItem)))
{
if (fOutOfRange)
{
//
// remove the item whose timestamp is out of range
//
CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut));
}
else
{
CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp));
if (NULL != bstrTimeStamp)
{
if ((NULL != bstrBeginDateTime) && (0 != SysStringLen(bstrBeginDateTime)) &&
(CompareBSTRs(bstrTimeStamp, bstrBeginDateTime) < 0))
{
//
// remove the item whose timestamp is out of range;
// set the flag to ignore the timestamp comparison for the rest of nodes
//
CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut));
fOutOfRange = TRUE;
}
else if ((NULL != bstrEndDateTime) && (0 != SysStringLen(bstrEndDateTime)) &&
(CompareBSTRs(bstrTimeStamp, bstrEndDateTime) > 0))
{
//
// remove the item whose timestamp is out of range
//
CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut));
}
else
{
CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_CLIENT, &pNodeClient));
CleanUpIfFailedAndSetHrMsg(GetText(pNodeClient, &bstrClientInfo));
if ((NULL != bstrClient) && (0 != SysStringLen(bstrClient)) &&
(WUCompareStringI(OLE2T(bstrClientInfo), OLE2T(bstrClient)) != CSTR_EQUAL))
{
//
// remove the item whose clieninfo does not match what we need
//
CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut));
}
}
}
}
SafeReleaseNULL(pNodeItem);
SafeReleaseNULL(pNodeItemOut);
SafeReleaseNULL(pNodeClient);
SafeSysFreeString(bstrTimeStamp);
SafeSysFreeString(bstrClientInfo);
}
}
}
}
CleanUp:
CloseItemList(hNodeList);
SafeReleaseNULL(pNodeItems);
SafeReleaseNULL(pNodeItem);
SafeReleaseNULL(pNodeItemOut);
SafeReleaseNULL(pNodeClient);
SysFreeString(bstrTimeStamp);
SysFreeString(bstrClientInfo);
if (SUCCEEDED(hr))
{
hr = GetItemsBSTR(pbstrXmlHistory);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CXmlClientInfo
CXmlClientInfo::CXmlClientInfo()
: m_pDocClientInfo(NULL)
{
}
CXmlClientInfo::~CXmlClientInfo()
{
SafeReleaseNULL(m_pDocClientInfo);
}
//
// load and parse and validate an XML document from string
//
HRESULT CXmlClientInfo::LoadXMLDocument(BSTR bstrXml, BOOL fOfflineMode)
{
LOG_Block("CXmlClientInfo::LoadXMLDocument()");
SafeReleaseNULL(m_pDocClientInfo);
HRESULT hr = LoadXMLDoc(bstrXml, &m_pDocClientInfo, fOfflineMode);
if (FAILED(hr))
{
LOG_ErrorMsg(hr);
}
return hr;
}
//
// retrieve client name attribute
//
HRESULT CXmlClientInfo::GetClientName(BSTR* pbstrClientName)
{
HRESULT hr= E_UNEXPECTED;
IXMLDOMElement* pElement = NULL;
BSTR bstrTagName = NULL;
VARIANT vAttr;
VariantInit(&vAttr);
LOG_Block("GetClientName()");
if (NULL == pbstrClientName)
{
return E_INVALIDARG;
}
if (NULL == m_pDocClientInfo)
{
return hr;
}
hr = m_pDocClientInfo->get_documentElement(&pElement);
CleanUpIfFailedAndMsg(hr);
if (NULL == pElement)
{
//
// no root element
//
hr = E_INVALIDARG; // clientInfo is bad! return this error back to caller
LOG_ErrorMsg(hr);
goto CleanUp;
}
hr = pElement->get_tagName(&bstrTagName);
CleanUpIfFailedAndMsg(hr);
if (!CompareBSTRsEqual(bstrTagName, KEY_CLIENTINFO))
{
//
// root is not clientInfo
//
hr = E_INVALIDARG;
LOG_ErrorMsg(hr);
goto CleanUp;
}
hr = pElement->getAttribute(KEY_CLIENTNAME, &vAttr);
CleanUpIfFailedAndMsg(hr);
if (VT_BSTR == vAttr.vt)
{
*pbstrClientName = SysAllocString(vAttr.bstrVal);
}
else
{
hr = E_FAIL;
CleanUpIfFailedAndMsg(hr);
}
CleanUp:
SafeReleaseNULL(pElement);
if (bstrTagName)
{
SysFreeString(bstrTagName);
bstrTagName = NULL;
}
VariantClear(&vAttr);
return hr;
}