/* * 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( 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( 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; }