1838 lines
61 KiB
C++
1838 lines
61 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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;
|
||
|
}
|