592 lines
12 KiB
C++
592 lines
12 KiB
C++
//==========================================================================
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
// PURPOSE.
|
|
//
|
|
// Copyright 1998 - 1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
extern HINSTANCE g_hmodThisDll; // Handle to this DLL itself.
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericEnum::CGenericEnum, public
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CGenericEnum::CGenericEnum(LPGENERICITEMLIST pGenericItemList,DWORD cOffset)
|
|
{
|
|
DWORD dwItemIndex;
|
|
m_cRef = 1; // give the intial reference
|
|
m_pGenericItemList = pGenericItemList;
|
|
m_cOffset = cOffset;
|
|
|
|
AddRef_ItemList(m_pGenericItemList); // increment our hold on shared memory.
|
|
|
|
// set the current item to point to next record.
|
|
m_pNextItem = m_pGenericItemList->pFirstGenericItem;
|
|
dwItemIndex = cOffset;
|
|
|
|
// this is a bug if this happens so assert in final.
|
|
if (dwItemIndex > m_pGenericItemList->dwNumItems)
|
|
dwItemIndex = 0;
|
|
|
|
// move the nextItem pointer to the proper position
|
|
while(dwItemIndex--)
|
|
{
|
|
m_pNextItem = m_pNextItem->pNextGenericItem;
|
|
++m_cOffset;
|
|
|
|
if (NULL == m_pNextItem)
|
|
break; // Again, another error.
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericEnum::~CGenericEnum, public
|
|
//
|
|
// Synopsis: Destructor.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CGenericEnum::~CGenericEnum()
|
|
{
|
|
Release_ItemList(m_pGenericItemList); // decrement our hold on shared memory.
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericEnum::QueryInterface, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CGenericEnum::QueryInterface(REFIID riid, LPVOID FAR *ppv)
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericEnum::Addref, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CGenericEnum::AddRef()
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericEnum::Release, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CGenericEnum::Release()
|
|
{
|
|
if (--m_cRef)
|
|
return m_cRef;
|
|
|
|
DeleteThisObject();
|
|
|
|
return 0L;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericEnum::Next, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CGenericEnum::Next(ULONG celt, LPGENERICITEM rgelt,ULONG *pceltFetched)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
ULONG ulFetchCount = celt;
|
|
ULONG ulNumFetched = 0;
|
|
LPGENERICITEM pGenericItem;
|
|
|
|
if ( (m_cOffset + celt) > m_pGenericItemList->dwNumItems)
|
|
{
|
|
ulFetchCount = m_pGenericItemList->dwNumItems - m_cOffset;
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
pGenericItem = rgelt;
|
|
|
|
while (ulFetchCount--)
|
|
{
|
|
*pGenericItem = *(m_pNextItem->pNextGenericItem);
|
|
m_pNextItem = m_pNextItem->pNextGenericItem; // add error checking
|
|
++m_cOffset;
|
|
++ulNumFetched;
|
|
++pGenericItem;
|
|
}
|
|
|
|
if (pceltFetched)
|
|
{
|
|
*pceltFetched = ulNumFetched;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericEnum::Skip, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CGenericEnum::Skip(ULONG celt)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ( (m_cOffset + celt) > m_pGenericItemList->dwNumItems)
|
|
{
|
|
m_cOffset = m_pGenericItemList->dwNumItems;
|
|
m_pNextItem = NULL;
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
while (celt--)
|
|
{
|
|
++m_cOffset;
|
|
m_pNextItem = m_pNextItem->pNextGenericItem;
|
|
}
|
|
|
|
hr = NOERROR;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericEnum::Reset, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CGenericEnum::Reset()
|
|
{
|
|
m_pNextItem = m_pGenericItemList->pFirstGenericItem;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericEnum::Clone, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CGenericEnum::Clone(CGenericEnum **ppenum)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
// help functions for managing enum list
|
|
// helper functions for managing the Generics list.
|
|
// properly increments and destroys shared Genericlist in memory.
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddRef_ItemList, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD AddRef_ItemList(LPGENERICITEMLIST pGenericItemList)
|
|
{
|
|
return ++pGenericItemList->_cRefs;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Release_ItemList, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Release_ItemList(LPGENERICITEMLIST pGenericItemList)
|
|
{
|
|
DWORD cRefs;
|
|
|
|
// bug, not threadsafe
|
|
cRefs = --pGenericItemList->_cRefs;
|
|
|
|
if (0 == pGenericItemList->_cRefs)
|
|
{
|
|
LPGENERICITEM pCurItem = pGenericItemList->pFirstGenericItem;
|
|
|
|
while(pCurItem)
|
|
{
|
|
LPGENERICITEM pFreeItem = pCurItem;
|
|
|
|
pCurItem = pCurItem->pNextGenericItem;
|
|
FREE(pFreeItem);
|
|
}
|
|
|
|
FREE(pGenericItemList);
|
|
}
|
|
|
|
return cRefs;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateItemList, public
|
|
//
|
|
// Synopsis: create an new list and initialize it to nothing
|
|
// and set the refcount to 1.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LPGENERICITEMLIST CreateItemList()
|
|
{
|
|
LPGENERICITEMLIST lpGenericList = (LPGENERICITEMLIST) ALLOC(sizeof(GENERICITEMLIST));
|
|
|
|
if (lpGenericList)
|
|
{
|
|
memset(lpGenericList,0,sizeof(GENERICITEMLIST));
|
|
AddRef_ItemList(lpGenericList);
|
|
}
|
|
|
|
return lpGenericList;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DuplicateList, public
|
|
//
|
|
// Synopsis: Duplicates the list
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LPGENERICITEMLIST DuplicateItemList(LPGENERICITEMLIST pItemList)
|
|
{
|
|
LPGENERICITEMLIST lpNewItemList;
|
|
LPGENERICITEM pCurItem;
|
|
|
|
lpNewItemList = CreateItemList();
|
|
if (!lpNewItemList)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pCurItem = pItemList->pFirstGenericItem;
|
|
|
|
while (pCurItem)
|
|
{
|
|
LPGENERICITEM pNewItemInList;
|
|
|
|
Assert(pCurItem->cbSize >= sizeof(GENERICITEM));
|
|
|
|
pNewItemInList = CreateNewListItem(pCurItem->cbSize);
|
|
|
|
if (pNewItemInList)
|
|
{
|
|
memcpy(pNewItemInList,pCurItem,pCurItem->cbSize);
|
|
pNewItemInList->pNextGenericItem = NULL;
|
|
AddItemToList(lpNewItemList,pNewItemInList);
|
|
}
|
|
|
|
pCurItem = pCurItem->pNextGenericItem;
|
|
}
|
|
|
|
return lpNewItemList;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddNewItemToList, public
|
|
//
|
|
// Synopsis: allocates space for a new item and adds it to the list,
|
|
// if successfull returns pointer to new item so caller can initialize it.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LPGENERICITEM AddNewItemToList(LPGENERICITEMLIST lpGenericList,ULONG cbSize)
|
|
{
|
|
LPGENERICITEM pNewGenericItem;
|
|
|
|
pNewGenericItem = CreateNewListItem(cbSize);
|
|
|
|
if (pNewGenericItem)
|
|
{
|
|
if (!AddItemToList(lpGenericList,pNewGenericItem))
|
|
{
|
|
FREE(pNewGenericItem);
|
|
pNewGenericItem = NULL;
|
|
}
|
|
}
|
|
|
|
return pNewGenericItem;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddItemToList, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL AddItemToList(LPGENERICITEMLIST lpGenericList,LPGENERICITEM pNewGenericItem)
|
|
{
|
|
LPGENERICITEM pGenericItem;
|
|
|
|
if (!pNewGenericItem || !lpGenericList)
|
|
{
|
|
Assert(lpGenericList);
|
|
Assert(pNewGenericItem);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pNewGenericItem)
|
|
{
|
|
Assert(pNewGenericItem->cbSize >= sizeof(GENERICITEM));
|
|
|
|
pGenericItem = lpGenericList->pFirstGenericItem;
|
|
|
|
if (NULL == pGenericItem)
|
|
{
|
|
lpGenericList->pFirstGenericItem = pNewGenericItem;
|
|
}
|
|
else
|
|
{
|
|
while (pGenericItem->pNextGenericItem)
|
|
pGenericItem = pGenericItem->pNextGenericItem;
|
|
|
|
pGenericItem->pNextGenericItem = pNewGenericItem;
|
|
|
|
}
|
|
|
|
++lpGenericList->dwNumItems;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteItemFromList, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL DeleteItemFromList(LPGENERICITEMLIST lpGenericList,LPGENERICITEM pGenericItem)
|
|
{
|
|
|
|
if (!pGenericItem || !lpGenericList)
|
|
{
|
|
Assert(lpGenericList);
|
|
Assert(pGenericItem);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pGenericItem)
|
|
{
|
|
LPGENERICITEM pCurItem;
|
|
GENERICITEM GenericItemTempHead;
|
|
|
|
Assert(pGenericItem->cbSize >= sizeof(GENERICITEM));
|
|
|
|
GenericItemTempHead.pNextGenericItem = lpGenericList->pFirstGenericItem;
|
|
pCurItem = &GenericItemTempHead;
|
|
|
|
|
|
while(pCurItem->pNextGenericItem)
|
|
{
|
|
|
|
if (pCurItem->pNextGenericItem == pGenericItem)
|
|
{
|
|
|
|
pCurItem->pNextGenericItem = pGenericItem->pNextGenericItem;
|
|
FREE(pGenericItem);
|
|
|
|
|
|
// update the head
|
|
lpGenericList->pFirstGenericItem = GenericItemTempHead.pNextGenericItem;
|
|
|
|
// update the number of items in the list
|
|
--lpGenericList->dwNumItems;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
pCurItem = pCurItem->pNextGenericItem;
|
|
}
|
|
|
|
}
|
|
|
|
AssertSz(0,"Didn't find item in List");
|
|
return FALSE; // didn't find anything.
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateNewListItem, public
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LPGENERICITEM CreateNewListItem(ULONG cbSize)
|
|
{
|
|
LPGENERICITEM pNewGenericItem;
|
|
|
|
// size must be at least size of the base generic item.
|
|
if (cbSize < sizeof(GENERICITEM))
|
|
return NULL;
|
|
|
|
pNewGenericItem = (LPGENERICITEM) ALLOC(cbSize);
|
|
|
|
// add item to the end of the list so if commit we do
|
|
// it in the same order items were added.
|
|
|
|
if (pNewGenericItem)
|
|
{
|
|
// initialize to zero, and then add it to the list.
|
|
memset(pNewGenericItem,0,cbSize);
|
|
pNewGenericItem->cbSize = cbSize;
|
|
}
|
|
|
|
return pNewGenericItem;
|
|
}
|