1 /* 2 * IEnumIDList 3 * 4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "precomp.h" 22 23 WINE_DEFAULT_DEBUG_CHANNEL(shell); 24 25 CEnumIDListBase::CEnumIDListBase() : 26 mpFirst(NULL), 27 mpLast(NULL), 28 mpCurrent(NULL) 29 { 30 } 31 32 CEnumIDListBase::~CEnumIDListBase() 33 { 34 DeleteList(); 35 } 36 37 /************************************************************************** 38 * AddToEnumList() 39 */ 40 BOOL CEnumIDListBase::AddToEnumList(LPITEMIDLIST pidl) 41 { 42 ENUMLIST *pNew; 43 44 TRACE("(%p)->(pidl=%p)\n", this, pidl); 45 46 if (!pidl) 47 return FALSE; 48 49 pNew = static_cast<ENUMLIST *>(SHAlloc(sizeof(ENUMLIST))); 50 if (pNew) 51 { 52 /*set the next pointer */ 53 pNew->pNext = NULL; 54 pNew->pidl = pidl; 55 56 /*is This the first item in the list? */ 57 if (!mpFirst) 58 { 59 mpFirst = pNew; 60 mpCurrent = pNew; 61 } 62 63 if (mpLast) 64 { 65 /*add the new item to the end of the list */ 66 mpLast->pNext = pNew; 67 } 68 69 /*update the last item pointer */ 70 mpLast = pNew; 71 TRACE("-- (%p)->(first=%p, last=%p)\n", this, mpFirst, mpLast); 72 return TRUE; 73 } 74 return FALSE; 75 } 76 77 /************************************************************************** 78 * DeleteList() 79 */ 80 BOOL CEnumIDListBase::DeleteList() 81 { 82 ENUMLIST *pDelete; 83 84 TRACE("(%p)->()\n", this); 85 86 while (mpFirst) 87 { 88 pDelete = mpFirst; 89 mpFirst = pDelete->pNext; 90 SHFree(pDelete->pidl); 91 SHFree(pDelete); 92 } 93 mpFirst = NULL; 94 mpLast = NULL; 95 mpCurrent = NULL; 96 return TRUE; 97 } 98 99 HRESULT CEnumIDListBase::AppendItemsFromEnumerator(IEnumIDList* pEnum) 100 { 101 LPITEMIDLIST pidl; 102 DWORD dwFetched; 103 104 if (!pEnum) 105 return E_INVALIDARG; 106 107 pEnum->Reset(); 108 109 while((S_OK == pEnum->Next(1, &pidl, &dwFetched)) && dwFetched) 110 AddToEnumList(pidl); 111 112 return S_OK; 113 } 114 115 /************************************************************************** 116 * IEnumIDList_fnNext 117 */ 118 119 HRESULT WINAPI CEnumIDListBase::Next( 120 ULONG celt, 121 LPITEMIDLIST * rgelt, 122 ULONG *pceltFetched) 123 { 124 ULONG i; 125 HRESULT hr = S_OK; 126 LPITEMIDLIST temp; 127 128 TRACE("(%p)->(%d,%p, %p)\n", this, celt, rgelt, pceltFetched); 129 130 /* It is valid to leave pceltFetched NULL when celt is 1. Some of explorer's 131 * subsystems actually use it (and so may a third party browser) 132 */ 133 if(pceltFetched) 134 *pceltFetched = 0; 135 136 *rgelt=0; 137 138 if(celt > 1 && !pceltFetched) 139 { return E_INVALIDARG; 140 } 141 142 if(celt > 0 && !mpCurrent) 143 { return S_FALSE; 144 } 145 146 for(i = 0; i < celt; i++) 147 { if(!mpCurrent) 148 { hr = S_FALSE; 149 break; 150 } 151 152 temp = ILClone(mpCurrent->pidl); 153 if (!temp) 154 { hr = i ? S_FALSE : E_OUTOFMEMORY; 155 break; 156 } 157 rgelt[i] = temp; 158 mpCurrent = mpCurrent->pNext; 159 } 160 if(pceltFetched) 161 { *pceltFetched = i; 162 } 163 164 return hr; 165 } 166 167 /************************************************************************** 168 * IEnumIDList_fnSkip 169 */ 170 HRESULT WINAPI CEnumIDListBase::Skip( 171 ULONG celt) 172 { 173 DWORD dwIndex; 174 HRESULT hr = S_OK; 175 176 TRACE("(%p)->(%u)\n", this, celt); 177 178 for(dwIndex = 0; dwIndex < celt; dwIndex++) 179 { if(!mpCurrent) 180 { hr = S_FALSE; 181 break; 182 } 183 mpCurrent = mpCurrent->pNext; 184 } 185 return hr; 186 } 187 188 /************************************************************************** 189 * IEnumIDList_fnReset 190 */ 191 HRESULT WINAPI CEnumIDListBase::Reset() 192 { 193 TRACE("(%p)\n", this); 194 mpCurrent = mpFirst; 195 return S_OK; 196 } 197 198 /************************************************************************** 199 * IEnumIDList_fnClone 200 */ 201 HRESULT WINAPI CEnumIDListBase::Clone(LPENUMIDLIST *ppenum) 202 { 203 TRACE("(%p)->() to (%p)->() E_NOTIMPL\n", this, ppenum); 204 return E_NOTIMPL; 205 } 206 207 /************************************************************************** 208 * IEnumIDList_Folder_Constructor 209 * 210 */ 211 HRESULT IEnumIDList_Constructor(IEnumIDList **enumerator) 212 { 213 return ShellObjectCreator<CEnumIDListBase>(IID_PPV_ARG(IEnumIDList, enumerator)); 214 } 215