windows-nt/Source/XPSP1/NT/enduser/windows.com/wuau/wuaueng/auxml.cpp

1838 lines
61 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 2000
//
// File: auxml.cpp
//
// About: source file for AU related XML and schema data structure and functions
//--------------------------------------------------------------------------
#include "pch.h"
//when changed, search for all occurrance of m_pFieldNames for needed modifications
//fixcode: get rid of EULA stuff.
LPSTR AUCatalogItem::m_pFieldNames[] = {"ItemID", "ProviderName", "Title", "Description", "RTFPath" , "EulaPath"};
#ifdef DBG
void DBGShowNodeName(IXMLDOMNode *pNode)
{
BSTR bsNodeName;
if (SUCCEEDED(pNode->get_nodeName(&bsNodeName)))
{
DEBUGMSG("node name is %S", bsNodeName);
}
else
{
DEBUGMSG("FAIL to get node name");
}
}
void DBGDumpXMLNode(IXMLDOMNode *pNode)
{
BSTR bsNodeName = NULL;
BSTR bsNodeXML = NULL;
if (SUCCEEDED(pNode->get_nodeName(&bsNodeName)) &&
(SUCCEEDED(pNode->get_xml(&bsNodeXML))))
{
DEBUGMSG("XML for %S is %S", bsNodeName, bsNodeXML);
}
SafeFreeBSTR(bsNodeName);
SafeFreeBSTR(bsNodeXML);
}
#endif
#if 0
void DBGDumpXMLDocProperties(IXMLDOMDocument2 *pDoc)
{
BSTR bsSelectionLanguage, bsSelectionNamespaces, bsServerHTTPRequest;
VARIANT vVal;
VariantInit(&vVal);
pDoc->getProperty(L"SelectionLanguage", &vVal);
DEBUGMSG("XMLDoc selection language is %S", vVal.bstrVal);
VariantClear(&vVal);
pDoc->getProperty(L"SelectionNamespaces", &vVal);
DEBUGMSG("XMLDoc selection namespaces is %S", vVal.bstrVal);
VariantClear(&vVal);
pDoc->getProperty(L"ServerHTTPRequest", &vVal);
DEBUGMSG("XMLDoc ServerHTTPRequest is %s", vVal.boolVal ? "True" : "False");
VariantClear(&vVal);
}
#endif
BSTR ReadXMLFromFile(IN LPCTSTR szFileName)
{
TCHAR tszFullFileName[MAX_PATH];
IXMLDOMDocument *pxml = NULL;
BSTR bstrXml = NULL;
// USES_CONVERSION;
// DEBUGMSG("ReadXMLFromFile() starts");
AUASSERT(_T('\0') != g_szWUDir[0]);
if(FAILED(StringCchCopyEx(tszFullFileName, ARRAYSIZE(tszFullFileName), g_szWUDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(StringCchCatEx(tszFullFileName, ARRAYSIZE(tszFullFileName), szFileName, NULL, NULL, MISTSAFE_STRING_FLAGS)))
{
DEBUGMSG("file name or path too long");
goto done;
}
if (!fFileExists(tszFullFileName))
{
DEBUGMSG("%S doesn't exists on disk", tszFullFileName);
}
else
{
CAU_BSTR aubsFullFileName;
HRESULT hr;
if (!aubsFullFileName.append(T2W(tszFullFileName)))
{
DEBUGMSG("Out of memory, fail to create string");
goto done;
}
if (FAILED(hr = LoadDocument(aubsFullFileName, &pxml, TRUE))) //offline
{
DEBUGMSG("Fail to load xml document %S with error %#lx", tszFullFileName, hr);
goto done;
}
if (FAILED(hr = pxml->get_xml(&bstrXml)))
{
DEBUGMSG("Fail to get xml string from document with error %#lx", hr);
goto done;
}
}
done:
SafeRelease(pxml);
// DEBUGMSG("ReadXMLFromFile() ends");
return bstrXml;
}
HRESULT MungleIdentity(IN IXMLDOMNode *pIdentity, IN DWORD dwSuffix)
{
BSTR bstrItemName = NULL;
CAU_BSTR aubsTmp;
WCHAR wcsBuf[12]; //will accomodate the maxium dword
HRESULT hr = S_OK;
if (0 == dwSuffix)
{
goto done;
}
if (NULL == pIdentity)
{
hr = E_INVALIDARG;
goto done;
}
if (FAILED(hr = GetAttribute(pIdentity, KEY_NAME, &bstrItemName)))
{ DEBUGMSG("Fail to get name from identity with error %#lx", hr);
goto done;
}
if (FAILED(StringCchPrintfExW(wcsBuf, ARRAYSIZE(wcsBuf), NULL, NULL, MISTSAFE_STRING_FLAGS, L"%lu", dwSuffix)) ||
!aubsTmp.append(bstrItemName) ||
!aubsTmp.append(L"_") ||
!aubsTmp.append(wcsBuf))
{
DEBUGMSG("OUT OF MEMORY");
hr = E_OUTOFMEMORY;
goto done;
}
if (FAILED(hr = SetAttribute(pIdentity, KEY_NAME, aubsTmp)))
{
DEBUGMSG("Fail to set attribute with error %#lx", hr);
goto done;
}
done:
SafeFreeBSTR(bstrItemName);
return hr;
}
BSTR GetPattern(IN LPCSTR szFieldName)
{
if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[0]))
{
return AUCatalog::bstrItemIDPattern;
}
else
if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[1]))
{
return AUCatalog::bstrProviderNamePattern;
}
else
if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[2]))
{
return AUCatalog::bstrTitlePattern;
}
else
if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[3]))
{
return AUCatalog::bstrDescPattern;
}
else
if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[4]))
{
return AUCatalog::bstrRTFUrlPattern;
}
else
if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[5]))
{
return AUCatalog::bstrEulaUrlPattern;
}
else
{
return NULL;
}
}
BOOL IsPersistedHiddenItem(IN BSTR bstrItemID, IN AUCatalogItemList & hiddenItemList)
{
BOOL fRet = (hiddenItemList.Contains(bstrItemID) >=0);
DEBUGMSG("%S is %s hidden item ", bstrItemID, fRet? "" : "NOT");
return fRet;
}
BOOL CItemDetails::Init(IN BSTR bsItemDetails)
{
BOOL fRet = TRUE;
if (FAILED(CoCreateInstance(__uuidof(DOMDocument), NULL, CLSCTX_INPROC_SERVER, __uuidof( IXMLDOMDocument), (void**)&m_pxml)))
{
DEBUGMSG("CItemDetails::Init() fail to create XML document");
fRet = FALSE;
goto end;
}
if (FAILED(m_pxml->put_async(VARIANT_FALSE))
||FAILED(m_pxml->put_resolveExternals(VARIANT_FALSE))
|| FAILED(m_pxml->put_validateOnParse(VARIANT_FALSE)))
{
fRet = FALSE;
goto end;
}
VARIANT_BOOL fOk;
if (S_OK != m_pxml->loadXML(bsItemDetails, &fOk))
{
DEBUGMSG("CItemDetails::Init() fail to load XML");
fRet = FALSE;
}
end:
if (!fRet)
{
SafeReleaseNULL(m_pxml);
}
return fRet;
}
//should be callable event without Init() called first
void CItemDetails::Uninit()
{
SafeRelease(m_pxml);
}
HRESULT CItemDetails::GetItemIdentities(IN BSTR bstrItemId, OUT IXMLDOMNodeList ** ppIdentityNodeList)
{
CAU_BSTR aubsPattern;
HRESULT hr = S_OK ;
// DEBUGMSG("CItemDetails::getIdentityNode() starts");
*ppIdentityNodeList = NULL;
if (!aubsPattern.append(L"/catalog/provider/item/identity[@itemID=\"") || !aubsPattern.append(bstrItemId) || !aubsPattern.append(L"\"]"))
{
DEBUGMSG("failed to create pattern string");
hr = E_OUTOFMEMORY;
goto done;
}
if (FAILED(hr = m_pxml->selectNodes(aubsPattern, ppIdentityNodeList)))
{
DEBUGMSG(" failed to find identityNode %#lx", hr);
goto done;
}
done:
// DEBUGMSG("CItemDetails::getIdentityNode() done");
return hr;
}
////////////////////////////////////////////////////////////////////////////
// delete all items with ITEMID=bstrItemId
///////////////////////////////////////////////////////////////////////////
HRESULT CItemDetails::DeleteItem(IN BSTR bstrItemId)
{
HRESULT hr = E_FAIL;
IXMLDOMNode *pItemNode = NULL;
IXMLDOMNode *pProviderNode = NULL;
IXMLDOMNode *pCatalogNode = NULL;
while (NULL != ( pItemNode = getItemNode(bstrItemId)))
{
if (FAILED(hr = pItemNode->get_parentNode(&pProviderNode)) || NULL == pProviderNode)
{
DEBUGMSG(" fail to get provider node %#lx", hr);
goto done;
}
if (FAILED(hr = pProviderNode->removeChild(pItemNode, NULL)))
{
DEBUGMSG(" fail to remove item node with error %#lx", hr);
goto done;
}
// DEBUGMSG("one item removed");
pItemNode ->Release();
pItemNode = NULL;
if (S_FALSE == (hr =pProviderNode->selectSingleNode(KEY_ITEM, &pItemNode)))
{
//provider had no children
if (FAILED(hr = pProviderNode->get_parentNode(&pCatalogNode)) || NULL == pCatalogNode)
{
DEBUGMSG(" fail to get catalog node %#lx", hr);
goto done;
}
if (FAILED(hr = pCatalogNode->removeChild(pProviderNode, NULL)))
{
DEBUGMSG(" fail to remove provider node with error %#lx", hr);
goto done;
}
// DEBUGMSG("one provider removed");
}
SafeReleaseNULL(pItemNode);
SafeReleaseNULL(pProviderNode);
SafeReleaseNULL(pCatalogNode);
}
done:
SafeRelease(pItemNode);
SafeRelease(pProviderNode);
SafeRelease(pCatalogNode);
return hr;
}
HRESULT CItemDetails::GetXML(BSTR *pbstrxml)
{
return m_pxml->get_xml(pbstrxml);
}
IXMLDOMNode * CItemDetails::getIdentityNode(IN BSTR bstrItemId)
{
IXMLDOMNode * pIdentityNode = NULL ;
CAU_BSTR aubsPattern;
HRESULT hr ;
// DEBUGMSG("CItemDetails::getIdentityNode() starts");
if (!aubsPattern.append(L"/catalog/provider/item/identity[@itemID=\"") || !aubsPattern.append(bstrItemId) || !aubsPattern.append(L"\"]"))
{
DEBUGMSG("failed to create pattern string");
goto done;
}
if (FAILED(hr = m_pxml->selectSingleNode(aubsPattern, &pIdentityNode)))
{
DEBUGMSG(" failed to find identityNode %#lx", hr);
goto done;
}
if (NULL == pIdentityNode)
{
goto done;
}
done:
// DEBUGMSG("CItemDetails::getIdentityNode() done");
return pIdentityNode;
}
/////////////////////////////////////////////////////////
// caller should make sure item bstrItemId exists in itemdetails
////////////////////////////////////////////////////////
BOOL CItemDetails::IsVisible(IN BSTR bstrItemId)
{
IXMLDOMNode * pItemNode = getItemNode(bstrItemId);
IXMLDOMNode *pDescriptionNode = NULL;
LONG lRet = 0;
HRESULT hr ;
// DEBUGMSG("IsVisible() starts");
//fixcode: really should return error instead of bogus TRUE
if (NULL == pItemNode )
{
DEBUGMSG("fail to find node or fail to create string");
goto done;
}
if (FAILED(hr = pItemNode->selectSingleNode(KEY_DESCRIPTION, &pDescriptionNode)) || NULL == pDescriptionNode)
{
DEBUGMSG("Fail to select node %S with error %#lx", KEY_DESCRIPTION, hr);
goto done;
}
if (FAILED(hr = GetAttribute(pDescriptionNode, KEY_HIDDEN, &lRet)))
{
DEBUGMSG("Fail to get attribute %S with error %#lx", KEY_HIDDEN, hr);
goto done;
}
// DEBUGMSG("Hidden attribute is %d for item %S", lRet, bstrItemId);
done:
SafeRelease(pDescriptionNode);
SafeRelease(pItemNode);
// DEBUGMSG("IsVisible() return %s for %S", (0 == lRet) ? "true" : "false", bstrItemId);
return 0 == lRet;
}
IXMLDOMNode * CItemDetails::getItemNode(IN BSTR bsItemId)
{
IXMLDOMNode * pIdentityNode = getIdentityNode(bsItemId);
IXMLDOMNode * pItemNode = NULL;
HRESULT hr;
//DEBUGMSG("CItemDetails::getItemNode() starts");
if (NULL == pIdentityNode)
{
goto done;
}
if (FAILED(hr = pIdentityNode->get_parentNode(&pItemNode)) || NULL == pItemNode)
{
DEBUGMSG(" fail to get item node %#lx", hr);
goto done;
}
done:
SafeRelease(pIdentityNode);
//DEBUGMSG("CItemDetails::getItemNode() ends");
return pItemNode;
}
HRESULT CItemDetails::CloneIdentityNode(IN BSTR bsItemId, IN IXMLDOMDocument *pDesXml, OUT IXMLDOMNode ** ppDesNode)
{
IXMLDOMNode * pIdentityNode ;
HRESULT hr = E_FAIL;
// DEBUGMSG("CItemDetails::CloneIdentityNode() starts");
*ppDesNode = NULL;
if (NULL == (pIdentityNode = getIdentityNode(bsItemId)))
{
goto done;
}
if (FAILED(hr = CopyNode(pIdentityNode, pDesXml, ppDesNode)))
{
DEBUGMSG("CItemDetails::CloneIdentityNode() failed to clone identityNode %#lx", hr);
}
done:
SafeRelease(pIdentityNode);
// DEBUGMSG("CItemDetails::CloneIdentityNode() ends");
return hr;
}
HRESULT CItemDetails::CloneDescriptionNode(IN BSTR bsItemId, IN IXMLDOMDocument *pDesXml, OUT IXMLDOMNode **ppDesNode)
{
IXMLDOMNode * pItemNode = getItemNode(bsItemId);
IXMLDOMNode * pDescriptionNode = NULL;
HRESULT hr = E_FAIL;
*ppDesNode = NULL;
if (NULL == pItemNode)
{
goto done;
}
if (!FindNode(pItemNode, KEY_DESCRIPTION, &pDescriptionNode))
{
DEBUGMSG("CItemDetails::CloneDescriptionNode() fail to get description node");
goto done;
}
if (FAILED(hr = CopyNode(pDescriptionNode, pDesXml, ppDesNode)))
{
DEBUGMSG("CItemDetails::CloneDescriptionNode() fail to clone node %#lx", hr);
}
done:
SafeRelease(pItemNode);
SafeRelease(pDescriptionNode);
return hr;
}
HRESULT CItemDetails::ClonePlatformNode(IN BSTR bsItemId, IN IXMLDOMDocument *pDesXml, OUT IXMLDOMNode **ppDesNode)
{
IXMLDOMNode * pItemNode = getItemNode(bsItemId);
IXMLDOMNode * pPlatformNode = NULL;
HRESULT hr = E_FAIL;
*ppDesNode = NULL;
if (NULL == pItemNode)
{
goto done;
}
if (!FindNode(pItemNode, KEY_PLATFORM, &pPlatformNode))
{
DEBUGMSG("CItemDetails::ClonePlatformNode() fail to get platform node");
goto done;
}
if (FAILED(hr = CopyNode(pPlatformNode, pDesXml, ppDesNode)))
{
DEBUGMSG("CItemDetails::ClonePlatformNode() fail to clone node %#lx", hr);
}
done:
SafeRelease(pItemNode);
SafeRelease(pPlatformNode);
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////
// retrieve cab names associated with an item identified by bsitemid
// called should free ppCabNames allocated in the function
// *pCabsNum contains number of cab names returned
////////////////////////////////////////////////////////////////////////////////////////
HRESULT CItemDetails::GetCabNames(IN BSTR bsItemId, OUT BSTR ** ppCRCCabNames, OUT BSTR **ppRealCabNames, OUT BSTR **ppCabChecksums, OUT UINT *pCabsNum)
{
IXMLDOMNode * pItemNode = getItemNode(bsItemId);
IXMLDOMNodeList *pCodeBaseNodes = NULL;
BSTR * pCRCCabNames = NULL;
BSTR * pRealCabNames = NULL;
BSTR * pCabChecksums = NULL;
UINT uCabsNum = 0;
CAU_BSTR aubsCodeBase;
HRESULT hr = E_FAIL;
//DEBUGMSG("CItemDetails::GetCabNames() starts");
*ppRealCabNames = *ppCRCCabNames = *ppCabChecksums = NULL;
*pCabsNum = 0;
if (!aubsCodeBase.append(L"installation/codeBase"))
{
DEBUGMSG("fail to create aubs");
goto done;
}
if (NULL == pItemNode)
{
goto done;
}
if (FAILED(hr = pItemNode->selectNodes(aubsCodeBase, &pCodeBaseNodes)) || NULL == pCodeBaseNodes)
{
DEBUGMSG("Fail to find codebase section");
goto done;
}
if (FAILED(hr = pCodeBaseNodes->get_length((long *) &uCabsNum)))
{
DEBUGMSG("Fail to get number of code base nodes with error %#lx", hr);
goto done;
}
pCRCCabNames = (BSTR*) malloc(uCabsNum * sizeof(*pCRCCabNames));
pRealCabNames = (BSTR*) malloc(uCabsNum * sizeof(*pRealCabNames));
pCabChecksums = (BSTR*) malloc(uCabsNum * sizeof(*pCabChecksums));
if (NULL != pCRCCabNames)
{
ZeroMemory((PVOID)pCRCCabNames, uCabsNum * sizeof(*pCRCCabNames));
}
if (NULL != pRealCabNames)
{
ZeroMemory((PVOID)pRealCabNames, uCabsNum * sizeof(*pRealCabNames));
}
if (NULL != pCabChecksums)
{
ZeroMemory((PVOID)pCabChecksums, uCabsNum * sizeof(*pCabChecksums));
}
if (NULL == pCRCCabNames || NULL == pRealCabNames || NULL == pCabChecksums)
{
DEBUGMSG("Fail to alloc memory for CRCCabsNames or RealCabNames");
hr = E_OUTOFMEMORY;
goto done;
}
for (UINT i = 0; i < uCabsNum ; i++)
{
IXMLDOMNode *pCodeBaseNode;
if (S_OK != (hr = pCodeBaseNodes->get_item(i, &pCodeBaseNode)))
{
DEBUGMSG("Fail to get codebase %d", i);
hr = FAILED(hr) ? hr : E_FAIL;
goto done;
}
if (FAILED(hr = GetAttribute(pCodeBaseNode, KEY_HREF, &(pCRCCabNames[i]))))
{
DEBUGMSG("Fail to get attribute %S", KEY_HREF);
pCodeBaseNode->Release();
goto done;
}
if (FAILED(hr = GetAttribute(pCodeBaseNode, KEY_NAME, &(pRealCabNames[i]))))
{
DEBUGMSG("Fail to get attribute %S", KEY_NAME);
pCodeBaseNode->Release();
goto done;
}
//Since CRC is optional, it might not exist for this cab
GetAttribute(pCodeBaseNode, KEY_CRC, &(pCabChecksums[i]));
pCodeBaseNode->Release();
}
*ppCRCCabNames = pCRCCabNames;
*ppRealCabNames = pRealCabNames;
*ppCabChecksums = pCabChecksums;
*pCabsNum = uCabsNum;
done:
SafeRelease(pCodeBaseNodes);
SafeRelease(pItemNode);
if (FAILED(hr))
{
if (NULL != pCRCCabNames)
{
for (UINT j = 0; j < uCabsNum; j++)
{
SafeFreeBSTR(pCRCCabNames[j]);
}
free(pCRCCabNames);
}
if (NULL != pRealCabNames)
{
for (UINT j = 0; j < uCabsNum; j++)
{
SafeFreeBSTR(pRealCabNames[j]);
}
free(pRealCabNames);
}
if (NULL != pCabChecksums)
{
for (UINT j = 0; j < uCabsNum; j++)
{
SafeFreeBSTR(pCabChecksums[j]);
}
free(pCabChecksums);
}
}
//DEBUGMSG("CItemDetails::GetCabNames() ends");
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////
// retrieve the CRC for the rtf file for the specified item
// caller should free pRTFCRC allocated in the function
////////////////////////////////////////////////////////////////////////////////////////
HRESULT CItemDetails::GetRTFCRC(BSTR bstrItemId, BSTR *pRTFCRC)
{
IXMLDOMNode * pItemNode = getItemNode(bstrItemId);
IXMLDOMNode *pDetailsNode = NULL;
CAU_BSTR aubsDetails;
HRESULT hr = E_FAIL;
AUASSERT(NULL != pRTFCRC);
*pRTFCRC = NULL;
if( NULL == pItemNode ||
!aubsDetails.append(L"description/descriptionText/details"))
{
goto done;
}
if (FAILED(hr = pItemNode->selectSingleNode(aubsDetails, &pDetailsNode)) ||
NULL == pDetailsNode)
{
DEBUGMSG("Fail to find details section");
goto done;
}
if (FAILED(hr = GetAttribute(pDetailsNode, KEY_CRC, pRTFCRC)) ||
hr == S_FALSE) //GetAttribute returns S_FALSE if the attribute does not exist for the node
{
DEBUGMSG("Fail to get attribute RTF crc, hr is %x", hr);
hr = (hr == S_FALSE) ? E_FAIL : hr;
}
done:
if(FAILED(hr))
{
SafeFreeBSTRNULL(*pRTFCRC);
}
SafeRelease(pItemNode);
SafeRelease(pDetailsNode);
return hr;
}
BSTR CItemDetails::GetItemDownloadPath(IN BSTR bstrItemId)
{
// USES_CONVERSION; only needed for ansi version
BSTR bstrRet = NULL;
IXMLDOMNode * pIdentityNode= NULL;
// DEBUGMSG("CItemDetails::GetItemDownloadPath starts");
if (NULL == (pIdentityNode = getIdentityNode(bstrItemId)))
{
goto done;
}
BSTR bstrdownloadPath;
if (FAILED(UtilGetUniqIdentityStr(pIdentityNode, &bstrdownloadPath, 0)))
{
DEBUGMSG("GetItemDownloadPath() fail to get unique identity string");
goto done;
}
TCHAR tszPath[MAX_PATH];
if (SUCCEEDED(GetCabsDownloadPath(tszPath, ARRAYSIZE(tszPath))) &&
SUCCEEDED(StringCchCatEx(tszPath, ARRAYSIZE(tszPath), _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) &&
SUCCEEDED(StringCchCatEx(tszPath, ARRAYSIZE(tszPath), W2T(bstrdownloadPath), NULL, NULL, MISTSAFE_STRING_FLAGS)))
{
bstrRet = SysAllocString(T2W(tszPath));
}
SysFreeString(bstrdownloadPath);
done:
SafeRelease(pIdentityNode);
/// DEBUGMSG("CItemDetails::GetItemDownloadPath() got %S", bstrRet);
if (NULL != bstrRet && !EnsureDirExists(W2T(bstrRet)))
{
DEBUGMSG("CItemDetails::GetItemDownloadPath() fail to create directory %S", bstrRet);
SysFreeString(bstrRet);
bstrRet = NULL;
}
return bstrRet;
}
HRESULT CItemDetails::GetItemIds(OUT long *plItemNum, OUT BSTR ** ppbstrItemIds)
{
IXMLDOMNodeList *pItemIdsNodeList = NULL;
HRESULT hr = E_FAIL;
// DEBUGMSG("CItemDetails::GetItemIds() starts");
*ppbstrItemIds = NULL;
*plItemNum = 0;
if (FAILED(hr = m_pxml->selectNodes(AUCatalog::bstrItemIdsPattern, &pItemIdsNodeList)))
{
DEBUGMSG(" fail to find item id with error %#lx", hr);
goto done;
}
if (FAILED(hr = pItemIdsNodeList->get_length(plItemNum)))
{
DEBUGMSG("Fail to get itemids number with error %#lx", hr);
goto done;
}
*ppbstrItemIds = (BSTR *) malloc((*plItemNum) * sizeof(**ppbstrItemIds));
if (NULL == *ppbstrItemIds)
{
DEBUGMSG("Fail to allocate memory for item ids");
hr = E_OUTOFMEMORY;
goto done;
}
ZeroMemory(*ppbstrItemIds, (*plItemNum) * sizeof(**ppbstrItemIds));
for (int i = 0; i < *plItemNum; i++)
{
IXMLDOMNode *pItemIdNode = NULL;
if (FAILED(hr = pItemIdsNodeList->get_item(i, &pItemIdNode)) || NULL == pItemIdNode)
{
DEBUGMSG("Fail to get item id node with error %#lx", hr);
hr = FAILED(hr) ? hr : E_FAIL;
goto done;
}
if (FAILED(hr = pItemIdNode->get_text(&((*ppbstrItemIds)[i]))) || NULL == (*ppbstrItemIds)[i])
{
DEBUGMSG("Fail to get item id no. %d with error %#lx", i+1, hr);
pItemIdNode->Release();
hr = FAILED(hr) ? hr : E_FAIL;
goto done;
}
pItemIdNode->Release();
// DEBUGMSG(" got #%d item id %S", i+1, (*ppbstrItemIds)[i]);
}
done:
SafeRelease(pItemIdsNodeList);
if (FAILED(hr))
{
if (NULL != *ppbstrItemIds)
{
for (int j = 0; j < *plItemNum; j++)
{
SafeFreeBSTR((*ppbstrItemIds)[j]);
}
SafeFree(*ppbstrItemIds);
}
*plItemNum = 0;
*ppbstrItemIds = NULL;
}
else
{
DEBUGMSG(" got %d item ids", *plItemNum);
}
// DEBUGMSG("CItemDetails::GetItemIds() ends");
return hr;
}
HRESULT CItemDetails::GetItemInfo(IN LPCSTR szFieldName, IN const BSTR bstrItemId, OUT BSTR * pbstrItemInfo)
{
HRESULT hr = E_FAIL;
IXMLDOMNode * pItemNode = getItemNode(bstrItemId);
IXMLDOMNode * pProviderNode = NULL;
IXMLDOMNode * pParentNode;
IXMLDOMNode *pItemInfoNode = NULL;
// DEBUGMSG("GetItemInfo() for %s starts", szFieldName);
*pbstrItemInfo = NULL;
if (NULL == pItemNode)
{
DEBUGMSG("Fail to get item node for %S", bstrItemId);
goto done;
}
//special case provider name
if (0 == _strcmpi(szFieldName, AUCatalogItem::m_pFieldNames[1]))
{
if (FAILED(hr = pItemNode->get_parentNode(&pProviderNode)) || NULL == pProviderNode)
{
DEBUGMSG("Fail to get provider node");
hr = E_FAIL;
goto done;
}
pParentNode = pProviderNode;
}
else
{
pParentNode = pItemNode;
}
if (FAILED(hr = FindSingleDOMNode(pParentNode, GetPattern(szFieldName), &pItemInfoNode)))
{
DEBUGMSG("Fail to get field %s for item %S", szFieldName, bstrItemId);
goto done;
}
if (FAILED(hr = pItemInfoNode->get_text(pbstrItemInfo))) //NULL content is fine
{
DEBUGMSG("Fail to get value from title node with error %#lx", hr);
goto done;
}
// DEBUGMSG(" item info %s is %S", szFieldName, *pbstrItemInfo);
done:
SafeRelease(pItemNode);
SafeRelease(pItemInfoNode);
SafeRelease(pProviderNode);
if (FAILED(hr))
{
SafeFreeBSTRNULL(*pbstrItemInfo);
}
// DEBUGMSG("GetItemInfo() for %s ends", szFieldName);
return hr;
}
//////////////////////////////////////////////////////////////////////////////////
//find first exclusive item that is NOT hidden and visible
//return S_OK if found one
//return S_FALSE if found none
//return E_FAIL if error occurs
HRESULT CItemDetails::FindFirstExclusiveItem(OUT BSTR *pbstrItemId, IN AUCatalogItemList & hiddenItemList)
{
IXMLDOMNodeList *pExclusiveItemNodes = NULL;
HRESULT hr = E_FAIL;
BOOL fFound = FALSE;
DEBUGMSG("CItemDetails::FindFirstExclusiveItem() starts");
*pbstrItemId = NULL;
pExclusiveItemNodes = FindDOMNodeList(m_pxml, AUCatalog::bstrExclusiveItemPattern);
if (NULL == pExclusiveItemNodes)
{
DEBUGMSG("No exclusive item found");
hr = S_FALSE;
goto done;
}
long lNum;
if (FAILED(hr = pExclusiveItemNodes->get_length(&lNum)))
{
DEBUGMSG("Fail to get exclusive item nodes number with error %#lx", hr);
goto done;
}
for (long l = 0; l < lNum; l++)
{
IXMLDOMNode *pExclusiveItemNode = NULL;
if (S_OK != (hr = pExclusiveItemNodes->get_item(l, &pExclusiveItemNode)))
{
DEBUGMSG("Fail to get item with error %#lx", hr);
hr = FAILED(hr) ? hr : E_FAIL;
goto done;
}
if (!FindNodeValue(pExclusiveItemNode, GetPattern(AUCatalogItem::m_pFieldNames[0]), pbstrItemId))
{
hr = E_FAIL;
}
pExclusiveItemNode->Release();
if (FAILED(hr))
{
DEBUGMSG("Fail to get item id text with error %#lx", hr);
goto done;
}
if (!IsPersistedHiddenItem(*pbstrItemId, hiddenItemList) && IsVisible(*pbstrItemId))
{
fFound = TRUE;
break;
}
SysFreeString(*pbstrItemId);
*pbstrItemId = NULL;
}
if (fFound)
{
DEBUGMSG("Find first exclusive item %S", *pbstrItemId);
hr = S_OK;
}
else
{
DEBUGMSG("No unhidden and visible exclusive item found");
hr = S_FALSE;
}
done:
SafeRelease(pExclusiveItemNodes);
if (S_OK != hr)
{
SafeFreeBSTRNULL(*pbstrItemId);
}
DEBUGMSG("CItemDetails::FindFirstExclusiveItem() ends");
return hr;
}
//////////////////////////////////////////////////////////////////////////////
// populate m_DependentItems of each item in the lsit with direct dependency
// Also check the self containment of depending items with in the list, i.e. all the depending items should
// also be in the list. If not, the dependency will not be recorded.
// return S_OK : if item found and dependency built if any
// E_XXXX: if error
//////////////////////////////////////////////////////////////////////////////
HRESULT CItemDetails::BuildDirectDependency(IN OUT AUCatalogItemList &itemlist)
{
HRESULT hr = S_OK;
CAU_BSTR aubsDependentItemID;
// DEBUGMSG("CItemDetails::BuildDirectDependency starts");
if (!aubsDependentItemID.append(L"dependencies/identity/@itemID"))
{
hr = E_OUTOFMEMORY;
goto done;
}
for (UINT i = 0; i < itemlist.Count(); i++)
{
IXMLDOMNodeList *pItemIDNodes = NULL;
IXMLDOMNode *pItemNode = NULL;
if (NULL == (pItemNode = getItemNode(itemlist[i].bstrID())))
{
// DEBUGMSG("Warning: item %S not found in the list", itemlist[i].bstrID()); //legitimate error
continue;
}
if (NULL == (pItemIDNodes = FindDOMNodeList(pItemNode, aubsDependentItemID)))
{
// DEBUGMSG ("No dependency found for item %S", itemlist[i].bstrID());
pItemNode->Release();
continue;
}
long lNumOfDependency;
if (FAILED(hr = pItemIDNodes->get_length(&lNumOfDependency)))
{
DEBUGMSG("Fail to get item id node number with error %#lx", hr);
pItemNode->Release();
pItemIDNodes->Release();
continue;
}
for (long l = 0; l < lNumOfDependency; l++)
{
IXMLDOMNode * pItemIDNode = NULL;
if (S_OK == pItemIDNodes->get_item(l, &pItemIDNode))
{
BSTR bstrItemId = NULL;
if (FAILED(hr = pItemIDNode->get_text(&bstrItemId)) || NULL == bstrItemId)
{
DEBUGMSG("Fail to get text for item id with error %#lx", hr);
hr = FAILED(hr) ? hr : E_FAIL;
pItemIDNode->Release();
break;
}
pItemIDNode->Release();
AUCatalogItem *pdependingItem = new AUCatalogItem;
if (NULL == pdependingItem)
{
DEBUGMSG("Out of Memory. Fail to create new item");
hr = E_OUTOFMEMORY;
SafeFreeBSTR(bstrItemId);
break;
}
if (NULL == bstrItemId)
{//although schema does not require itemid, we do
DEBUGMSG("Fail to find item id");
hr = E_FAIL;
delete pdependingItem;
break;
}
INT index = itemlist.Contains(bstrItemId);
if (index >= 0)
{
BSTR bstrTmp = SysAllocString(itemlist[i].bstrID());
if (NULL == bstrTmp)
{
DEBUGMSG("Fail to allocate memory");
SysFreeString(bstrItemId);
delete pdependingItem;
hr = E_OUTOFMEMORY;
break;
}
pdependingItem->SetField(AUCatalogItem::m_pFieldNames[0], bstrTmp);
if (!itemlist[index].m_DependingItems.Add(pdependingItem))
{
DEBUGMSG("fail to add depending item");
SysFreeString(bstrItemId);
delete pdependingItem;
hr = E_OUTOFMEMORY;
break;
}
else
{
DEBUGMSG("item %S depending on item %S. Dependency recorded", pdependingItem->bstrID(), itemlist[index].bstrID());
}
}
else
{
DEBUGMSG("Warning: item %S depends on an item not in the list", itemlist[i].bstrID());
delete pdependingItem;
}
SysFreeString(bstrItemId);
}
else
{
DEBUGMSG("Error: fail to get item id node");
hr = E_FAIL;
break;
}
}
pItemNode->Release();
pItemIDNodes->Release();
}
done:
// DEBUGMSG("CItemDetails::BuildDirectDependency ends");
if (FAILED(hr))
{
for (UINT i = 0; i < itemlist.Count(); i++)
{
itemlist[i].m_DependingItems.Clear();
}
}
return hr;
}
////////////////////////////////////////////////////////////////////////////
// format of hidde.xml is
// <hiddenitems version = #>
// <item id = "...........">
// ..............
// <item id = "...........">
// </hiddenitems>
// return S_FALSE when no hidden items left in the xml file. The file will be deleted
///////////////////////////////////////////////////////////////////////////
// TO be finished
HRESULT PersistHiddenItems(IN AUCatalogItemList &itemlist, IN URLLOGACTIVITY activity)
{
// USES_CONVERSION;
IXMLDOMDocument *pHiddenXml = NULL;
IXMLDOMNode *pHiddenItemsNode = NULL;
IXMLDOMElement *pelemITEM = NULL;
TCHAR tszFullFileName[MAX_PATH];
CAU_BSTR aubsFullFileName;
CAU_BSTR aubsItemPattern;
UINT uItemAdded = 0;
HRESULT hr = S_OK;
DEBUGMSG("PersistHiddenItems() starts");
if (itemlist.GetNumUnselected() == 0)
{
DEBUGMSG("No hidden items to persist");
goto done;
}
AUASSERT(_T('\0') != g_szWUDir[0]);
if (FAILED(StringCchCopyEx(tszFullFileName, ARRAYSIZE(tszFullFileName), g_szWUDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(StringCchCatEx(tszFullFileName, ARRAYSIZE(tszFullFileName), HIDDEN_ITEMS_FILE, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
!aubsFullFileName.append(T2W(tszFullFileName)) ||
!aubsItemPattern.append(AUCatalog::bstrHiddenItems) ||
!aubsItemPattern.append(L"/") ||!aubsItemPattern.append(AUCatalog::bstrTagITEM))
{
DEBUGMSG("Fail to create string ");
hr = E_OUTOFMEMORY;
goto done;
}
if (fFileExists(tszFullFileName))
{
DEBUGMSG("file %S exists. Add hidden items to it", tszFullFileName);
if (FAILED(hr = LoadDocument(aubsFullFileName, &pHiddenXml, TRUE))) //offline
{
DEBUGMSG(" %S fail to load with error %#lx, delete it", aubsFullFileName, hr);
AUDelFileOrDir(tszFullFileName);
}
}
if (NULL == pHiddenXml)
{
if (FAILED(hr = LoadXMLDoc(AUCatalog::bstrTemplate, &pHiddenXml, TRUE))) //offline
{
DEBUGMSG("Fail to load template xml with error %#lx", hr);
goto done;
}
}
if (!FindNode(pHiddenXml, AUCatalog::bstrHiddenItems, &pHiddenItemsNode))
{
hr = E_FAIL;
DEBUGMSG("Fail to find node %S", AUCatalog::bstrHiddenItems);
goto done;
}
VARIANT varValueID;
varValueID.vt = VT_BSTR;
// write out item information
for ( DWORD index = 0; index < itemlist.Count(); index++ )
{
if (itemlist[index].fUnselected())
{ //hide unselected items
varValueID.bstrVal = itemlist[index].bstrID();
if ( FAILED(hr = pHiddenXml->createElement(AUCatalog::bstrTagITEM, &pelemITEM)) ||
FAILED(hr = pelemITEM->setAttribute(AUCatalog::bstrAttrID, varValueID)) ||
FAILED(hr = pHiddenItemsNode->appendChild(pelemITEM, NULL)) )
{
DEBUGMSG("XML operation failure with error %#lx", hr);
}
else
{
// DEBUGMSG("item %S persisted", itemlist[index].bstrID());
uItemAdded++;
gPingStatus.PingDeclinedItem(FALSE, activity, W2T(varValueID.bstrVal));
}
SafeReleaseNULL(pelemITEM);
// DEBUGMSG("Item %S now hidden", itemlist[index].bstrID());
itemlist[index].SetStatusHidden();
}
}
if (0 == uItemAdded)
{
DEBUGMSG("no new hidden items need to be persisted");
hr = S_OK;
}
else
if (FAILED(hr= SaveDocument(pHiddenXml, aubsFullFileName)))
{
DEBUGMSG("Fail to save hidden xml %S with error %#lx", T2W(tszFullFileName), hr);
AUDelFileOrDir(tszFullFileName);
goto done;
}
done:
SafeRelease(pelemITEM);
SafeRelease(pHiddenItemsNode);
SafeRelease(pHiddenXml);
DEBUGMSG("PersistHiddenItems() ends with %d items added", uItemAdded);
return hr;
}
//////////////////////////////////////////////////////////////////////
// read hidden xml file if there is one
// and populate the hidden item list passed in
// return S_FALSE if there is no hidden items found
/////////////////////////////////////////////////////////////////////
HRESULT GetPersistedHiddenItems(AUCatalogItemList OUT & hiddenItemList)
{
HRESULT hr ;
IXMLDOMNodeList *pItemNodes = NULL;
IXMLDOMDocument *pHiddenXml = NULL;
CAU_BSTR aubsItemPattern;
DEBUGMSG("GetPersistedHiddenItems() starts");
TCHAR tszFullFileName[MAX_PATH];
CAU_BSTR aubsFullFileName;
AUASSERT(_T('\0') != g_szWUDir[0]);
if (FAILED(StringCchCopyEx(tszFullFileName, ARRAYSIZE(tszFullFileName), g_szWUDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(StringCchCatEx(tszFullFileName, ARRAYSIZE(tszFullFileName), HIDDEN_ITEMS_FILE, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
!aubsItemPattern.append(AUCatalog::bstrHiddenItems) ||
!aubsItemPattern.append(L"/") ||
!aubsItemPattern.append(AUCatalog::bstrTagITEM) ||
!aubsFullFileName.append(T2W(tszFullFileName)))
{
DEBUGMSG("fail to create string");
hr = E_OUTOFMEMORY;
goto done;
}
if (!fFileExists(W2T(aubsFullFileName)))
{
DEBUGMSG("No persisted item found");
hr = S_FALSE;
goto done;
}
if (FAILED(hr = LoadDocument(aubsFullFileName, &pHiddenXml, TRUE))) //offline
{
DEBUGMSG(" %S fail to load with error %#lx", aubsFullFileName, hr); //might be expected if file is not there
goto done;
}
pItemNodes = FindDOMNodeList(pHiddenXml, aubsItemPattern);
if (NULL == pItemNodes)
{
hr = S_FALSE;
DEBUGMSG("no persisted hidden items found using pattern %S", aubsItemPattern);
goto done;
}
long lItemNum;
if (FAILED(hr = pItemNodes->get_length(&lItemNum)))
{
DEBUGMSG("fail to get number of item nodes with error %#lx", hr);
goto done;
}
for (int i = 0; i < lItemNum; i++)
{
IXMLDOMNode *pItemNode = NULL;
BSTR bstrItemID = NULL;
if (S_OK != (hr = pItemNodes->get_item(i, &pItemNode)))
{
DEBUGMSG("Fail to get item %d", i);
hr = FAILED(hr) ? hr : E_FAIL;
goto done;
}
hr = GetAttribute(pItemNode, AUCatalog::bstrAttrID, &bstrItemID);
SafeRelease(pItemNode);
if (FAILED(hr))
{
goto done;
}
if (NULL != bstrItemID)
{
AUCatalogItem *pItem = new AUCatalogItem();
if (NULL == pItem)
{
DEBUGMSG("Fail to create new item");
SysFreeString(bstrItemID);
hr = E_OUTOFMEMORY;
goto done;
}
else
{
pItem->SetField(AUCatalogItem::m_pFieldNames[0], bstrItemID);
DEBUGMSG("Find one hidden item %S", bstrItemID);
if (!hiddenItemList.Add(pItem))
{
DEBUGMSG("OUT OF MEMORY: fail to add item");
hr = E_OUTOFMEMORY;
delete pItem;
goto done;
}
}
}
}
done:
SafeRelease(pItemNodes);
SafeRelease(pHiddenXml);
if (hr != S_OK)
{
hiddenItemList.Clear();
}
DEBUGMSG("GetPersistedHiddenItems() ends");
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// given a details xml, extract all the items in it
// and populate the AU catalog item list passed in
// all the persisted hidden items will be excluded
// bstrDetails: IN details xml
// itemlist : IN/OUT receives items information
// fDriver: IN whether bstrDetails is for driver or non driver
// pfFoundExclusive: OUT TRUE if found exclusive item. In that case, only exclusive item will be returned
// return : TRUE if items got from the xml
// FALSE otherwise
/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL fExtractItemInfo(IN const BSTR bstrDetails, OUT AUCatalogItemList & itemList, OUT BOOL *pfFoundExclusive)
{
long lNumItems = 0;
BSTR *pbstrItemIds = NULL;
BOOL fRet = FALSE;
CItemDetails itemdetails;
BSTR bstrExclusiveItemId;
AUCatalogItemList hiddenItemList;
BOOL fHiddenItemsFound;
BOOL fItemIdsAllocated = FALSE;
HRESULT hr;
DEBUGMSG("fExtractItemInfo() starts");
*pfFoundExclusive = FALSE;
itemList.Clear();
if (!itemdetails.Init(bstrDetails))
{
DEBUGMSG("Fail to init itemdetails");
goto done;
}
if (FAILED(hr = GetPersistedHiddenItems(hiddenItemList)))
{
DEBUGMSG("no persisted hidden items loaded with error %#lx", hr);
}
if (*pfFoundExclusive = (S_OK == itemdetails.FindFirstExclusiveItem(&bstrExclusiveItemId, hiddenItemList)))
{
DEBUGMSG("Found exclusive item, add it");
lNumItems = 1;
pbstrItemIds = &bstrExclusiveItemId;
}
else
{
if (FAILED(hr = itemdetails.GetItemIds(&lNumItems, &pbstrItemIds)))
{
DEBUGMSG("Fail to get item ids with error %#lx", hr);
goto done;
}
else
{
fItemIdsAllocated = TRUE;
}
}
for (long i = 0; i < lNumItems; i++)
{
if (itemList.Contains(pbstrItemIds[i]) >=0)
{ //duplicate item id found
continue;
}
AUCatalogItem *pitem = new AUCatalogItem();
if (NULL == pitem)
{
DEBUGMSG("Out of memory and fail to create new item.");
goto done;
}
BSTR bstrTmp = SysAllocString(pbstrItemIds[i]);
if (NULL == bstrTmp)
{
DEBUGMSG("Out of memory ");
delete pitem;
goto done;
}
pitem->SetField(AUCatalogItem::m_pFieldNames[0], bstrTmp);
//even if one or more following item information is missing, add item anyway
for (int j = 1; j < ARRAYSIZE(AUCatalogItem::m_pFieldNames); j++)
{
BSTR bstrItemInfo = NULL;
if (FAILED(itemdetails.GetItemInfo(AUCatalogItem::m_pFieldNames[j], pbstrItemIds[i], &bstrItemInfo)))
{
continue;
}
pitem->SetField(AUCatalogItem::m_pFieldNames[j], bstrItemInfo);
}
if ( IsPersistedHiddenItem(pbstrItemIds[i], hiddenItemList) ||
!itemdetails.IsVisible(pbstrItemIds[i]))
{ //don't show non visible and hidden items
pitem->SetStatusHidden();
}
if (!itemList.Add(pitem))
{
DEBUGMSG("OUT OF MEMORY: fail to add new item");
delete pitem;
goto done;
}
}
fRet = TRUE;
done:
itemdetails.Uninit();
if (!fRet)
{
itemList.Clear();
}
for (int k = 0; k < lNumItems; k++)
{
SafeFreeBSTR(pbstrItemIds[k]);
}
if (fItemIdsAllocated)
{
SafeFree(pbstrItemIds);
}
DEBUGMSG("fExtractItemInfo() ends");
return fRet;
}
IXMLDOMNode * createDownloadItemStatusNode(IN IXMLDOMDocument * pxml, IN AUCatalogItem &Item, IN const BSTR bsInstallation, OUT IXMLDOMNode **ppIdentity)
{
IXMLDOMElement * pitemStatus = NULL;
BOOL fError = FALSE; //no error occurs
IXMLDOMNode * pdescription = NULL;
IXMLDOMNode * pPlatform = NULL;
IXMLDOMElement *pdownloadStatus = NULL;
IXMLDOMElement *pdownloadPath = NULL;
CItemDetails itemDetails;
BSTR bsItemId, bsdownloadPath = NULL;
VARIANT vComplete;
IXMLDOMNode ** ItemStatusChildren[] = {ppIdentity, &pdescription, &pPlatform};
DEBUGMSG("CAUCatalog::createDownloadItemStatusNode() starts");
*ppIdentity = NULL;
if (!itemDetails.Init(bsInstallation))
{
DEBUGMSG("fail to init itemdetails");
fError = TRUE;
goto done;
}
bsItemId = Item.bstrID();
DEBUGMSG("creating node for %S", bsItemId);
if (NULL == bsItemId)
{
DEBUGMSG("fails to get item id");
fError = TRUE;
goto done;
}
if (FAILED(pxml->createElement(KEY_ITEMSTATUS, &pitemStatus)) || NULL == pitemStatus)
{
DEBUGMSG("fail to create item status node");
fError = TRUE;
goto done;
}
itemDetails.CloneIdentityNode(bsItemId, pxml, ppIdentity);
itemDetails.CloneDescriptionNode(bsItemId, pxml, &pdescription);
itemDetails.ClonePlatformNode(bsItemId, pxml, &pPlatform);
if (NULL == *ppIdentity || NULL == pdescription || NULL == pPlatform)
{
fError = TRUE;
goto done;
}
for (int i = 0; i < ARRAYSIZE(ItemStatusChildren); i++)
{
if (FAILED(pitemStatus->appendChild(*(ItemStatusChildren[i]), NULL)))
{
DEBUGMSG("fail to append identy node");
fError = TRUE;
goto done;
}
}
if (FAILED(pxml->createElement(KEY_DOWNLOADPATH, &pdownloadPath)) || NULL == pdownloadPath)
{
DEBUGMSG("fail to create download path node");
fError = TRUE;
goto done;
}
bsdownloadPath = itemDetails.GetItemDownloadPath(bsItemId);
if (NULL == bsdownloadPath)
{
fError = TRUE;
goto done;
}
if (FAILED(pdownloadPath->put_text(bsdownloadPath)))
{
DEBUGMSG("fail to set download path text to %S", bsdownloadPath);
fError = TRUE;
goto done;
}
if (FAILED(pitemStatus->appendChild(pdownloadPath, NULL)))
{
DEBUGMSG("fail to append download path");
fError = TRUE;
goto done;
}
if (FAILED(pxml->createElement(KEY_DOWNLOADSTATUS, &pdownloadStatus)) || NULL == pdownloadStatus)
{
DEBUGMSG("fail to create download status node");
fError = TRUE;
goto done;
}
vComplete.vt = VT_BSTR;
vComplete.bstrVal = SysAllocString(L"COMPLETE");
if (NULL == vComplete.bstrVal)
{
DEBUGMSG("Out of memory, fail to create string complete");
fError = TRUE;
goto done;
}
HRESULT hr = SetAttribute(pdownloadStatus, KEY_DOWNLOADSTATUS, vComplete);
VariantClear(&vComplete);
if (FAILED(hr))
{
DEBUGMSG("fail to set download status attribute");
fError = TRUE;
goto done;
}
if (FAILED(pitemStatus->appendChild(pdownloadStatus, NULL)))
{
DEBUGMSG("fail to append download status node");
fError = TRUE;
goto done;
}
done:
itemDetails.Uninit();
SafeFreeBSTR(bsdownloadPath);
if (fError)
{
SafeRelease(*ppIdentity);
SafeRelease(pitemStatus);
*ppIdentity = NULL;
pitemStatus = NULL;
}
SafeRelease(pPlatform);
SafeRelease(pdescription);
SafeRelease(pdownloadPath);
SafeRelease(pdownloadStatus);
DEBUGMSG("CAUCatalog::createDownloadItemStatusNode() ends");
return pitemStatus;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
// *pbstrInstallation contains a subset of bsItemDetails (only items needs to be installed)
///////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT PrepareInstallXML(
IN BSTR bsItemDetails, //a superset of items in the itemlist
IN AUCatalogItemList &itemList,
OUT BSTR * pbstrDownloadResult,
OUT BSTR *pbstrInstallation)
{
DEBUGMSG("::PrepareInstallXML");
HRESULT hr = E_FAIL;
BSTR bsRet = NULL;
IXMLDOMNode * pItems = NULL;
IXMLDOMDocument *pxml = NULL;
CItemDetails itemdetails;
LONG lNumItems = 0;
BSTR * pbstrItemIds = NULL;
*pbstrDownloadResult = NULL;
*pbstrInstallation = NULL;
if (! itemdetails.Init(bsItemDetails))
{
DEBUGMSG("Fail to init item details ");
goto done;
}
if (FAILED(hr = LoadXMLDoc(AUCatalog::bstrResultTemplate, &pxml)))
{
DEBUGMSG("::PrepareInstallXML() fail to load download result template with error %#lx", hr);
goto done;
}
if (FAILED(hr = FindSingleDOMNode(pxml, KEY_ITEMS, &pItems)) || NULL == pItems)
{
DEBUGMSG("::PrepareInstallXML() fail to get items with error %#lx", hr);
goto done;
}
// DEBUGMSG("need to insert %d items in download result", itemList.GetNumSelected());
if (FAILED(hr = itemdetails.GetItemIds(&lNumItems, &pbstrItemIds)))
{
DEBUGMSG("Fail to get item ids with error %#lx", hr);
goto done;
}
for (LONG l = 0; l < lNumItems; l++)
{
if (itemList.Contains(pbstrItemIds[l]) < 0)
{
itemdetails.DeleteItem(pbstrItemIds[l]); //delete items not in the itemlist
}
}
for (UINT i = 0; i < itemList.Count(); i++)
{
AUCatalogItem & item = itemList[i];
if (item.fSelected() || itemList.ItemIsRelevant(i))
{
long lItemNum = 0;
IXMLDOMNodeList *pIdentityNodeList = NULL;
if (FAILED(itemdetails.GetItemIdentities(item.bstrID(), &pIdentityNodeList)))
{
DEBUGMSG("Fail to get item identities for item %S", item.bstrID());
continue;
}
if (FAILED(pIdentityNodeList->get_length(&lItemNum)))
{
DEBUGMSG("Fail to get number of identity nodes"); //fixcode: bail out here
pIdentityNodeList->Release();
continue;
}
for (long lIndex = 0; lIndex < lItemNum; lIndex++)
{
DEBUGMSG("Create download status node %d for item %S", lIndex, item.bstrID());
IXMLDOMNode * pDetailsIdentity = NULL;
IXMLDOMNode *pDownloadResultIdentity = NULL;
if (S_OK != pIdentityNodeList->get_item(lIndex, &pDetailsIdentity))
{
DEBUGMSG("Fail to get item %d", lIndex); //fixcode: bail out here
continue;
}
MungleIdentity(pDetailsIdentity, lIndex);
IXMLDOMNode * pItemStatus = createDownloadItemStatusNode(pxml, item, bsItemDetails, &pDownloadResultIdentity);
if (NULL != pItemStatus)
{
MungleIdentity(pDownloadResultIdentity, lIndex);
if (FAILED(hr = pItems->appendChild(pItemStatus,NULL)))
{
DEBUGMSG("fail to insert item %d", i);
}
else
{
DEBUGMSG("item %d inserted", i);
}
pItemStatus->Release();
}
SafeRelease(pDetailsIdentity);
SafeRelease(pDownloadResultIdentity);
}
pIdentityNodeList->Release();
}
else
{
itemdetails.DeleteItem(item.bstrID());
}
}
if ( FAILED(hr = pxml->get_xml(pbstrDownloadResult)) )
{
DEBUGMSG("::PrepareInstallXML() fail to get xml for the result %#lx", hr);
goto done;
}
if (FAILED(hr = itemdetails.GetXML(pbstrInstallation)))
{
DEBUGMSG(" fail to get xml for installation with error %#lx", hr);
goto done;
}
done:
itemdetails.Uninit();
SafeRelease(pItems);
SafeRelease(pxml);
for (int k = 0; k < lNumItems; k++)
{
SafeFreeBSTR(pbstrItemIds[k]);
}
if (lNumItems > 0)
{
SafeFree(pbstrItemIds);
}
if (FAILED(hr))
{
SafeFreeBSTR(*pbstrDownloadResult);
*pbstrDownloadResult = NULL;
SafeFreeBSTR(*pbstrInstallation);
*pbstrInstallation = NULL;
}
return hr;
}
///////////////////////////////////////////////////////////////////
// merge catalog 1 and catalog2 and make it destination catalog *pDesCatalog
// if either of bsCatalog1 and bsCatalog2 is NULL, return duplicate of the non NULL
// catalog
// if both bsCatalog1 and bsCatalog2 are NULL, return NULL and S_FALSE
//
///////////////////////////////////////////////////////////////////
HRESULT MergeCatalogs(IN const BSTR bsCatalog1, IN const BSTR bsCatalog2, OUT BSTR *pbsDesCatalog )
{
IXMLDOMDocument * pCat1 = NULL;
IXMLDOMDocument * pCat2 = NULL;
IXMLDOMNodeList *pProviderNodeList = NULL;
IXMLDOMNode *pCatalogNode = NULL;
HRESULT hr = E_FAIL;
DEBUGMSG("MergeCatalogs() starts");
*pbsDesCatalog = NULL;
if (NULL == bsCatalog1 && NULL == bsCatalog2)
{
return S_FALSE;
}
if (NULL == bsCatalog1 || NULL == bsCatalog2)
{
*pbsDesCatalog = SysAllocString((NULL == bsCatalog1) ? bsCatalog2 : bsCatalog1);
if (NULL == *pbsDesCatalog)
{
DEBUGMSG("Out of memory");
hr = E_OUTOFMEMORY;
goto done;
}
hr = S_OK;
goto done;
}
if ( FAILED(hr = LoadXMLDoc(bsCatalog1, &pCat1)) ||
FAILED(hr = LoadXMLDoc(bsCatalog2,&pCat2)))
{
DEBUGMSG("MergeCatalogs() fail to load xml or fail or allocate string (with error %#lx)", hr);
goto done;
}
if (FAILED(hr = FindSingleDOMNode(pCat1, AUCatalog::bstrCatalog, &pCatalogNode)))
{
DEBUGMSG("Fail to find provider in catalog 1");
goto done;
}
if (NULL == (pProviderNodeList = FindDOMNodeList(pCat2, KEY_CATALOG_PROVIDER)))
{
DEBUGMSG("Fail to find provider in catalog 2 with error %#lx", hr);
goto done;
}
long lNum;
if (FAILED(hr = pProviderNodeList->get_length(&lNum)))
{
DEBUGMSG("Fail to get nubmer of providers");
goto done;
}
for (int i = 0; i < lNum; i++)
{
IXMLDOMNode * pProviderNode = NULL;
if (S_OK != (hr = pProviderNodeList->get_item(i, &pProviderNode)))
{
DEBUGMSG("Fail to get item in Provider List with error %#lx", hr);
hr = FAILED(hr) ? hr : E_FAIL;
goto done;
}
if (FAILED(hr = InsertNode(pCatalogNode, pProviderNode)))
{
DEBUGMSG("Fail to append provider node from catalog 2 to catalog 1 with error %#lx", hr);
pProviderNode->Release();
goto done;
}
pProviderNode->Release();
}
if (FAILED(hr = pCat1->get_xml(pbsDesCatalog)))
{
DEBUGMSG("Fail to get result xml for catalog 1 with error %#lx", hr);
goto done;
}
done:
SafeRelease(pCat1);
SafeRelease(pCat2);
SafeRelease(pProviderNodeList);
SafeRelease(pCatalogNode);
if (FAILED(hr))
{
SafeFreeBSTRNULL(*pbsDesCatalog);
}
DEBUGMSG("MergeCatalogs() ends");
return hr;
}
////////////////////////////////////////////////////////////////////////////////////
// populate itemlist for all items in the list with detailed information from local merged catalog xml file
// also return the merged catalog xml in pbstrInstallation
// if fDrvierNeeded, care to extract driver information. Otherwise, no driver info extracted
/////////////////////////////////////////////////////////////////////////////////////
HRESULT GetDetailedItemInfoFromDisk(IN OUT AUCatalogItemList &ItemList, OUT BSTR *pbstrInstallation, IN BOOL fDriverNeeded)
{
HRESULT hr = S_OK;
CItemDetails driverDetails, nonDriverDetails;
BSTR bstrDriver = NULL;
BSTR bstrNonDriver = NULL;
*pbstrInstallation = NULL;
if (NULL == (bstrNonDriver = ReadXMLFromFile(DETAILS_FILE)) ||
(fDriverNeeded && (NULL == (bstrDriver = ReadXMLFromFile(DRIVERS_FILE)))))
{
DEBUGMSG("Fail to load driver or nondriver details xml file");
hr = E_FAIL;
goto done;
}
if (!nonDriverDetails.Init(bstrNonDriver) ||
(fDriverNeeded && !driverDetails.Init(bstrDriver)))
{
DEBUGMSG("Fail to initialize item or driver details ");
hr = E_FAIL;
goto done;
}
if (FAILED(hr = MergeCatalogs(bstrDriver, bstrNonDriver, pbstrInstallation)))
{
DEBUGMSG("Fail to merge catalog with error %#lx", hr);
goto done;
}
for (UINT u = 0; u < ItemList.Count(); u++)
{
for (int i = 1; i < ARRAYSIZE(AUCatalogItem::m_pFieldNames); i++)
{
BSTR bstrItemInfo = NULL;
if (SUCCEEDED(nonDriverDetails.GetItemInfo(AUCatalogItem::m_pFieldNames[i], ItemList[u].bstrID(), &bstrItemInfo)) ||
(fDriverNeeded && SUCCEEDED(driverDetails.GetItemInfo(AUCatalogItem::m_pFieldNames[i], ItemList[u].bstrID(), &bstrItemInfo))))
{
ItemList[u].SetField(AUCatalogItem::m_pFieldNames[i], bstrItemInfo);
}
else
{
DEBUGMSG("Warning: not getting information about %S for item %S", AUCatalogItem::m_pFieldNames[i], ItemList[u].bstrID());
}
}
}
done:
driverDetails.Uninit();
nonDriverDetails.Uninit();
if (FAILED(hr))
{
SafeFreeBSTR(*pbstrInstallation);
*pbstrInstallation = NULL;
}
SafeFreeBSTR(bstrDriver);
SafeFreeBSTR(bstrNonDriver);
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////
// walk through the whole list of items, hidden or non hidden, build dependency list m_DependentItems
// for each item from scratch. The orginal m_DependentItems for each item is discarded
// bstrDriver could be NULL
/////////////////////////////////////////////////////////////////////////////////////////
HRESULT BuildDependencyList(
AUCatalogItemList IN OUT &itemlist,
BSTR IN bstrDriver,
BSTR IN bstrNonDriver)
{
CItemDetails driverInfo;
CItemDetails nondriverInfo;
HRESULT hr = E_FAIL ;
BOOL fHasDriverUpdate = TRUE;
if (!nondriverInfo.Init(bstrNonDriver))
{
DEBUGMSG("Fail to initialize item details");
goto done;
}
if (NULL != bstrDriver)
{
if (!driverInfo.Init(bstrDriver) )
{
DEBUGMSG("Fail to initialize driver details");
goto done;
}
}
else
{
fHasDriverUpdate = FALSE;
}
DEBUGMSG("Building direct dependency for non drivers");
if (FAILED(hr = nondriverInfo.BuildDirectDependency(itemlist)))
{ //itemlist is a non driver and dependency built if any
DEBUGMSG("Fail to build dependency for non drivers with error %#lx", hr);
goto done;
}
if (fHasDriverUpdate)
{
DEBUGMSG("Building direct dependency for drivers");
if (FAILED(hr = driverInfo.BuildDirectDependency(itemlist)))
{ //itemlist is a driver and dependency built if any
DEBUGMSG("Fail to build dependency for drivers with error %#lx", hr);
goto done;
}
}
DEBUGMSG("Building indirect dependency");
if (FAILED(hr = itemlist.BuildIndirectDependency()))
{
DEBUGMSG("Fail to build indirect dependency for itemlist with error %#lx", hr);
goto done;
}
done:
if (fHasDriverUpdate)
{
driverInfo.Uninit();
}
nondriverInfo.Uninit();
DEBUGMSG("BuildDependencyList done");
#ifdef DBG
// itemlist.DbgDump();
#endif
return hr;
}