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