2025-04-27 07:49:33 -04:00

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;
}