windows-nt/Source/XPSP1/NT/com/mobile/syncmgr/sample/enum.cpp
2020-09-26 16:20:57 +08:00

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