350 lines
10 KiB
C++
350 lines
10 KiB
C++
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 2000
|
|
//
|
|
// File: ItemList.cpp
|
|
//
|
|
// Purpose: AU Item List
|
|
//
|
|
// Creator: PeterWi
|
|
//
|
|
// History: 08-27-01 first created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
#include "pch.h"
|
|
|
|
|
|
//=======================================================================
|
|
//
|
|
// AUCatalogItemList::Clear
|
|
//
|
|
//=======================================================================
|
|
void AUCatalogItemList::Clear(void)
|
|
{
|
|
if ( NULL != pList )
|
|
{
|
|
for ( DWORD index = 0; index < Count(); index++ )
|
|
{
|
|
delete pList[index];
|
|
}
|
|
}
|
|
SafeFreeNULL(pList);
|
|
uNum = 0;
|
|
}
|
|
|
|
UINT AUCatalogItemList::GetNum(DWORD dwSelectionStatus)
|
|
{
|
|
UINT nNum = 0;
|
|
|
|
for ( UINT index = 0; index < Count(); index++ )
|
|
{
|
|
if ( dwSelectionStatus == operator[](index).dwStatus() )
|
|
{
|
|
nNum++;
|
|
}
|
|
}
|
|
return nNum;
|
|
}
|
|
|
|
|
|
void AUCatalogItemList::DbgDump(void)
|
|
{
|
|
#ifdef DBG
|
|
DEBUGMSG("Iterating %d items in the list....", uNum);
|
|
for (UINT i = 0; i < uNum; i++)
|
|
{
|
|
pList[i]->dump();
|
|
}
|
|
DEBUGMSG("Iterating item list done");
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
//=======================================================================
|
|
//
|
|
// AUCatalogItemList::Allocate(DWORD cItems)
|
|
//
|
|
//=======================================================================
|
|
HRESULT AUCatalogItemList::Allocate(DWORD cItems)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD index = 0;
|
|
|
|
Clear();
|
|
|
|
//pList shouldn't be pointer to pointer
|
|
pList = (AUCatalogItem**)malloc(cItems * sizeof(AUCatalogItem *));
|
|
if ( NULL == pList )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
|
|
for ( index = 0; index < cItems; index++ )
|
|
{
|
|
pList[index] = (AUCatalogItem*) new AUCatalogItem;
|
|
if ( NULL == pList[index] )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
}
|
|
done:
|
|
if (FAILED(hr))
|
|
{
|
|
for (DWORD i = 0; i < index; i++)
|
|
{
|
|
delete pList[i];
|
|
}
|
|
free(pList);
|
|
}
|
|
|
|
uNum = SUCCEEDED(hr) ? cItems : 0;
|
|
return hr;
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//
|
|
// AUCatalogItemList::Allocate(VARIANT & var)
|
|
//
|
|
//=======================================================================
|
|
HRESULT AUCatalogItemList::Allocate(VARIANT & var)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
long UBound = 0;
|
|
long cItems;
|
|
|
|
if ( ((VT_ARRAY | VT_VARIANT) != var.vt) ||
|
|
FAILED(SafeArrayGetUBound(var.parray, 1, &UBound)) /*| (0 != (++cItems % 7))*/ )
|
|
{
|
|
// temp
|
|
DEBUGMSG("Invalid array");
|
|
hr = E_INVALIDARG;
|
|
goto done;
|
|
}
|
|
|
|
cItems = (UBound + 1) / 7;
|
|
DEBUGMSG("Variant Array size of %d", UBound + 1);
|
|
|
|
hr = Allocate(cItems);
|
|
done:
|
|
return hr;
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//
|
|
// AUCatalogItemList::Add
|
|
//
|
|
//=======================================================================
|
|
BOOL AUCatalogItemList::Add(AUCatalogItem *pitem)
|
|
{
|
|
AUCatalogItem** pNewList = (AUCatalogItem**)realloc(pList, (uNum+1)*sizeof(AUCatalogItem *));
|
|
|
|
BOOL fRet = (NULL != pNewList);
|
|
|
|
if ( fRet )
|
|
{
|
|
pList = pNewList;
|
|
pList[uNum] = pitem;
|
|
uNum++;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//=======================================================================
|
|
//
|
|
// AUCatalogItemList::Remove
|
|
//
|
|
//=======================================================================
|
|
void AUCatalogItemList::Remove(BSTR bstrItemID)
|
|
{
|
|
int index = -1;
|
|
AUASSERT(NULL != bstrItemID);
|
|
AUASSERT(L'\0' != *bstrItemID);
|
|
if (0 == SysStringLen(bstrItemID))
|
|
{
|
|
return ;
|
|
}
|
|
for (UINT u = 0; u < uNum; u++)
|
|
{
|
|
if (0 == StrCmpI(W2T(bstrItemID), W2T(pList[u]->bstrID())))
|
|
{
|
|
index = u;
|
|
break;
|
|
}
|
|
}
|
|
if (-1 == index)
|
|
{
|
|
//DEBUGMSG("Fail to find the item to remove");
|
|
return;
|
|
}
|
|
AUCatalogItem *ptmp;
|
|
ptmp = pList[index];
|
|
pList[index] = pList[uNum-1];
|
|
delete ptmp;
|
|
uNum--;
|
|
return;
|
|
}
|
|
|
|
//=======================================================================
|
|
//
|
|
// AUCatalogItemList::Contains
|
|
// returns -1 if item not found. index of the item if it is found
|
|
//=======================================================================
|
|
INT AUCatalogItemList::Contains(BSTR bstrItemID)
|
|
{
|
|
for (UINT u = 0; u < uNum; u++)
|
|
{
|
|
if (0 == StrCmpI(W2T(bstrItemID), W2T(pList[u]->bstrID())))
|
|
{
|
|
return u;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
HRESULT AUCatalogItemList::Copy(AUCatalogItemList & itemlist2)
|
|
{
|
|
AUASSERT(this != &itemlist2);
|
|
if (this == &itemlist2)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
long lNum = itemlist2.Count();
|
|
HRESULT hr = S_OK;
|
|
Clear();
|
|
for (long l = 0; l < lNum; l++)
|
|
{
|
|
AUCatalogItem *pItem = new AUCatalogItem(itemlist2[l]);
|
|
if ( NULL == pItem)
|
|
{
|
|
DEBUGMSG("Fail to create new aucatalog item");
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
if (!pItem->fEqual(itemlist2[l]) || !Add(pItem))
|
|
{
|
|
DEBUGMSG("Fail to create new item or add the new item");
|
|
delete pItem;
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
Clear();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// walk through each item in the list and use the m_DependentItems information to
|
|
// find all dependent items each item depends on indirectly, add them to m_DependentItems
|
|
// list.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT AUCatalogItemList::BuildIndirectDependency()
|
|
{
|
|
HRESULT hr = S_OK ;
|
|
BOOL fNeedMoreScan;
|
|
|
|
// DEBUGMSG("AUCatalogItemList::BuildIndirectDependency() starts");
|
|
do
|
|
{
|
|
fNeedMoreScan = FALSE;
|
|
for (UINT i = 0; i < uNum; i++)
|
|
{
|
|
if (pList[i]->m_DependingItems.Count() > 0)
|
|
{//has direct depending items
|
|
AUCatalogItem & item =operator[](i);
|
|
for (UINT j = 0; j < item.m_DependingItems.Count() ; j++)
|
|
{
|
|
INT directDependingItemIndex = Contains(item.m_DependingItems[j].bstrID());
|
|
if (directDependingItemIndex < 0)
|
|
{
|
|
DEBUGMSG("WARNING: item list is not self contained");
|
|
continue;
|
|
}
|
|
AUCatalogItem & directDependingItem = operator[](directDependingItemIndex);
|
|
// DEBUGMSG("direct depending item %S has %d depending items", directDependingItem.bstrID(), directDependingItem.m_DependingItems.Count());
|
|
for (UINT k = 0; k < directDependingItem.m_DependingItems.Count(); k++)
|
|
{ //add all one level deep indirect depending items, if not duplicated
|
|
INT indirectDependingItemIndex = Contains(directDependingItem.m_DependingItems[k].bstrID());
|
|
if (indirectDependingItemIndex < 0)
|
|
{
|
|
DEBUGMSG("WARNING: item list is not self contained");
|
|
continue;
|
|
}
|
|
AUCatalogItem &indirectDependingItem = operator[](indirectDependingItemIndex);
|
|
if (item.m_DependingItems.Contains(indirectDependingItem.bstrID()) < 0)
|
|
{ // need to add the indirect depending item
|
|
AUCatalogItem * pnewdependingItem = new AUCatalogItem(indirectDependingItem);
|
|
if (NULL == pnewdependingItem)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
if (!pnewdependingItem->fEqual(indirectDependingItem) || !item.m_DependingItems.Add(pnewdependingItem))
|
|
{
|
|
delete pnewdependingItem;
|
|
hr = E_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
|
|
DEBUGMSG("item %S indirectly depending on item %S. Dependency recorded", indirectDependingItem.bstrID(), item.bstrID());
|
|
fNeedMoreScan = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// DEBUGMSG("item %d indirect dependency alreay in", i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while (fNeedMoreScan);
|
|
done:
|
|
// DEBUGMSG("AUCatalogItemList::BuildIndirectDependency() ends with result %#lx", hr);
|
|
if (FAILED(hr))
|
|
{
|
|
for (UINT i = 0; i < Count(); i++)
|
|
{
|
|
pList[i]->m_DependingItems.Clear();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// check if item indexed is relevant in downloading and installation
|
|
// i.e. one or more of its depending items needs to be downloaded or installed (a.k.a selected)
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
BOOL AUCatalogItemList::ItemIsRelevant(UINT index)
|
|
{
|
|
if (index >= uNum)
|
|
{
|
|
AUASSERT(FALSE); //should never be here
|
|
return FALSE;
|
|
}
|
|
for (UINT i = 0; i < pList[index]->m_DependingItems.Count(); i++)
|
|
{
|
|
AUCatalogItem & dependingItem = pList[index]->m_DependingItems[i];
|
|
INT index2 = Contains(dependingItem.bstrID());
|
|
if (index2 >= 0 && pList[index2]->fSelected())
|
|
{
|
|
DEBUGMSG("Item %S is relevant because item %S is selected", pList[index2]->bstrID(), dependingItem.bstrID());
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|