mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5227 lines
150 KiB
5227 lines
150 KiB
//=======================================================================
|
|
//
|
|
// 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;
|
|
}
|