reactos/dll/win32/browseui/aclmulti.cpp

149 lines
4.1 KiB
C++

/*
* Multisource AutoComplete list
*
* Copyright 2007 Mikolaj Zalewski
* Copyright 2009 Andrew Hill
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "precomp.h"
void CACLMulti::release_obj(struct ACLMultiSublist *obj)
{
obj->punk->Release();
if (obj->pEnum)
obj->pEnum->Release();
if (obj->pACL)
obj->pACL->Release();
}
CACLMulti::CACLMulti()
{
fObjectCount = 0;
fCurrentObject = 0;
fObjects = NULL;
}
CACLMulti::~CACLMulti()
{
int i;
TRACE("destroying %p\n", this);
for (i = 0; i < fObjectCount; i++)
release_obj(&fObjects[i]);
CoTaskMemFree(fObjects);
}
HRESULT STDMETHODCALLTYPE CACLMulti::Append(IUnknown *punk)
{
TRACE("(%p, %p)\n", this, punk);
if (punk == NULL)
return E_FAIL;
fObjects = static_cast<ACLMultiSublist *>(
CoTaskMemRealloc(fObjects, sizeof(fObjects[0]) * (fObjectCount + 1)));
fObjects[fObjectCount].punk = punk;
punk->AddRef();
if (FAILED_UNEXPECTEDLY(punk->QueryInterface(IID_PPV_ARG(IEnumString, &fObjects[fObjectCount].pEnum))))
fObjects[fObjectCount].pEnum = NULL;
if (FAILED_UNEXPECTEDLY(punk->QueryInterface(IID_PPV_ARG(IACList, &fObjects[fObjectCount].pACL))))
fObjects[fObjectCount].pACL = NULL;
fObjectCount++;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CACLMulti::Remove(IUnknown *punk)
{
int i;
TRACE("(%p, %p)\n", this, punk);
for (i = 0; i < fObjectCount; i++)
if (fObjects[i].punk == punk)
{
release_obj(&fObjects[i]);
MoveMemory(&fObjects[i], &fObjects[i + 1], (fObjectCount - i - 1) * sizeof(ACLMultiSublist));
fObjectCount--;
fObjects = static_cast<ACLMultiSublist *>(
CoTaskMemRealloc(fObjects, sizeof(fObjects[0]) * fObjectCount));
return S_OK;
}
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE CACLMulti::Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
{
TRACE("(%p, %d, %p, %p)\n", this, celt, rgelt, pceltFetched);
while (fCurrentObject < fObjectCount)
{
if (fObjects[fCurrentObject].pEnum)
{
/* native browseui 6.0 also returns only one element */
HRESULT ret = fObjects[fCurrentObject].pEnum->Next(1, rgelt, pceltFetched);
if (ret != S_FALSE)
return ret;
}
fCurrentObject++;
}
if (pceltFetched)
*pceltFetched = 0;
*rgelt = NULL;
return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CACLMulti::Reset()
{
int i;
fCurrentObject = 0;
for (i = 0; i < fObjectCount; i++)
{
if (fObjects[i].pEnum)
fObjects[i].pEnum->Reset();
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CACLMulti::Skip(ULONG celt)
{
/* native browseui 6.0 returns this: */
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CACLMulti::Clone(IEnumString **ppOut)
{
*ppOut = NULL;
/* native browseui 6.0 returns this: */
return E_OUTOFMEMORY;
}
HRESULT STDMETHODCALLTYPE CACLMulti::Expand(LPCWSTR wstr)
{
HRESULT res = S_OK;
int i;
for (i = 0; i < fObjectCount; i++)
{
if (!fObjects[i].pACL)
continue;
res = fObjects[i].pACL->Expand(wstr);
if (res == S_OK)
break;
}
return res;
}