Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

304 lines
6.1 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995
//
// File: enumidl.cpp
//
// Contents: LPITEMIDLIST enumerator
//
// History: 5-6-95 Davepl,JonBe Created
//
//--------------------------------------------------------------------------
#include "precomp.h"
extern "C" HANDLE g_hProcessHeap;
//
// Constructor
//
CEnumOLEDB::CEnumOLEDB()
{
m_pIDListArray = NULL;
m_cElements = 0;
m_iIndex = 0;
m_cRefs = 1;
}
//
// Destructor
//
CEnumOLEDB::~CEnumOLEDB()
{
LPMALLOC pMalloc;
HRESULT hr;
if (m_pIDListArray)
{
hr = SHGetMalloc(&pMalloc);
if (SUCCEEDED(hr))
{
//
// Release all of the pidls in our table, then free the table
//
ASSERT(m_cElements == m_pIDListArray->GetSize());
for (int i = 0; i < m_cElements; i++)
{
pMalloc->Free(m_pIDListArray->GetAt(i));
}
pMalloc->Release();
delete m_pIDListArray;
}
else
{
dprintf(TEXT("*** Couldn't get allocator in ~CEnumOLEDB"));
}
}
else
{
dprintf(TEXT("Warning: CEnumOLEDB destructor called with NULL m_pIDListArray"));
}
}
//
// InitInstance
//
HRESULT CEnumOLEDB::InitInstance()
{
m_pIDListArray = new CIDListArray(g_hProcessHeap);
if (m_pIDListArray)
{
return NOERROR;
}
else
{
return E_OUTOFMEMORY;
}
}
//
// AddRef
//
STDMETHODIMP_(ULONG) CEnumOLEDB::AddRef()
{
InterlockedIncrement((LONG *) &m_cRefs);
return m_cRefs;
}
//
// Release
//
STDMETHODIMP_(ULONG) CEnumOLEDB::Release()
{
ULONG tmp = m_cRefs;
if (0 == InterlockedDecrement((LONG *) &m_cRefs))
{
delete this;
return 0;
}
else
{
return tmp - 1;
}
}
//
// QueryInterface
//
STDMETHODIMP CEnumOLEDB::QueryInterface(REFIID riid, LPVOID * ppvObj)
{
HRESULT hr;
if(IsEqualIID(riid, IID_IUnknown) ||
IsEqualIID(riid, IID_IEnumIDList) ||
IsEqualIID(riid, IID_IAsynchEnumIDList))
{
*ppvObj = this;
AddRef();
hr = S_OK;
}
else
{
*ppvObj = NULL;
hr = E_NOINTERFACE;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CEnumOLEDB::AddElement
//
// Synopsis: Adds a pidl to our enumerator
//
//--------------------------------------------------------------------------
HRESULT CEnumOLEDB::AddElement(LPITEMIDLIST pidl)
{
if (TRUE == m_pIDListArray->Add(pidl))
{
m_cElements++;
return S_OK;
}
else
{
return E_OUTOFMEMORY;
}
}
//
// Next
//
STDMETHODIMP CEnumOLEDB::Next(ULONG celtRequested,
LPITEMIDLIST* rgelt,
ULONG* pceltFetched)
{
//
// See how many elements we can return (the min of
// the number requested and the number left)
//
ULONG celtWillReturn = (ULONG) min(m_cElements - m_iIndex, (int) celtRequested);
ULONG celtFetched = celtWillReturn;
if (pceltFetched)
{
*pceltFetched = celtFetched;
}
while (celtWillReturn)
{
CIDList* pidl = (CIDList*) m_pIDListArray->GetAt(m_iIndex);
// The pointer is an invention from which programming languages may
// never recover...
//
// rgelt[x] is an IDLIST pointer, but we want the address of it to
// pass to clone to. &rgelt[x] is a ptr to a ptr to an IDLIST, which
// we cast to a ptr to a ptr to a CIDList, which is the same
// thing only with helper members.
if (SUCCEEDED( pidl->CloneTo( (CIDList **)(&rgelt[celtWillReturn - 1]) ) ))
{
celtWillReturn--;
m_iIndex++;
}
else
{
break;
}
}
return (celtRequested == celtFetched) ? S_OK : S_FALSE;
}
//
// Reset
//
STDMETHODIMP CEnumOLEDB::Reset()
{
m_iIndex = 0;
return S_OK;
}
//
// Clone (not implemented)
//
STDMETHODIMP CEnumOLEDB::Clone(IEnumIDList ** /* UNUSED ppenum */)
{
return E_NOTIMPL;
}
//
// Skip
//
STDMETHODIMP CEnumOLEDB::Skip(ULONG celtToSkip)
{
HRESULT hr;
if (m_iIndex + (int) celtToSkip > m_cElements)
{
m_iIndex = m_cElements;
hr = S_FALSE;
}
else
{
m_iIndex += (int) celtToSkip;
hr = S_OK;
}
return hr;
}
STDMETHODIMP CEnumOLEDB::NextAt(ULONG celtRequested,
ULONG iStart,
LPITEMIDLIST* rgelt,
ULONG* pceltFetched)
{
//
// See how many elements we can return (the min of
// the number requested and the number left)
//
ULONG celtFetched = (ULONG) min(m_cElements - iStart + 1, (int) celtRequested);
HRESULT hr;
ULONG iIndex = iStart; // Temp index -- don't want to change
// m_iIndex (though will there ever be
// mixed calls to Next() and NextAt()?)
if (pceltFetched)
{
*pceltFetched = celtFetched;
}
for (ULONG ulTemp = 0; ulTemp < celtFetched - 1; ulTemp++, iIndex++)
{
CIDList* pidl = (CIDList*) m_pIDListArray->GetAt(iIndex);
// rgelt[x] is an IDLIST pointer, but we want the address of it to
// pass to clone to. &rgelt[x] is a ptr to a ptr to an IDLIST, which
// we cast to a ptr to a ptr to a CIDList, which is the same
// thing only with helper members.
hr = pidl->CloneTo( (CIDList **)(&rgelt[ulTemp]) );
if (FAILED(hr))
{
// Cleanup everything and bail out
for (ULONG ulTemp2 = 0; ulTemp2 < ulTemp; ulTemp2++)
{
SHFree(rgelt[ulTemp2]);
}
if (pceltFetched)
{
*pceltFetched = 0;
}
return hr;
}
}
return (celtRequested == celtFetched) ? S_OK : S_FALSE;
}
STDMETHODIMP_(ULONG) CEnumOLEDB::GetCount()
{
return m_cElements;
}