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 /************************************************************************** 100 * HasItemWithCLSID() 101 */ 102 BOOL CEnumIDListBase::HasItemWithCLSID(LPITEMIDLIST pidl) 103 { 104 ENUMLIST *pCur; 105 IID *ptr = _ILGetGUIDPointer(pidl); 106 107 if (ptr) 108 { 109 REFIID refid = *ptr; 110 pCur = mpFirst; 111 112 while(pCur) 113 { 114 LPGUID curid = _ILGetGUIDPointer(pCur->pidl); 115 if (curid && IsEqualGUID(*curid, refid)) 116 { 117 return TRUE; 118 } 119 pCur = pCur->pNext; 120 } 121 } 122 123 return FALSE; 124 } 125 126 HRESULT CEnumIDListBase::AppendItemsFromEnumerator(IEnumIDList* pEnum) 127 { 128 LPITEMIDLIST pidl; 129 DWORD dwFetched; 130 131 if (!pEnum) 132 return E_INVALIDARG; 133 134 pEnum->Reset(); 135 136 while((S_OK == pEnum->Next(1, &pidl, &dwFetched)) && dwFetched) 137 AddToEnumList(pidl); 138 139 return S_OK; 140 } 141 142 /************************************************************************** 143 * IEnumIDList_fnNext 144 */ 145 146 HRESULT WINAPI CEnumIDListBase::Next( 147 ULONG celt, 148 LPITEMIDLIST * rgelt, 149 ULONG *pceltFetched) 150 { 151 ULONG i; 152 HRESULT hr = S_OK; 153 LPITEMIDLIST temp; 154 155 TRACE("(%p)->(%d,%p, %p)\n", this, celt, rgelt, pceltFetched); 156 157 /* It is valid to leave pceltFetched NULL when celt is 1. Some of explorer's 158 * subsystems actually use it (and so may a third party browser) 159 */ 160 if(pceltFetched) 161 *pceltFetched = 0; 162 163 *rgelt=0; 164 165 if(celt > 1 && !pceltFetched) 166 { return E_INVALIDARG; 167 } 168 169 if(celt > 0 && !mpCurrent) 170 { return S_FALSE; 171 } 172 173 for(i = 0; i < celt; i++) 174 { if(!mpCurrent) 175 { hr = S_FALSE; 176 break; 177 } 178 179 temp = ILClone(mpCurrent->pidl); 180 if (!temp) 181 { hr = i ? S_FALSE : E_OUTOFMEMORY; 182 break; 183 } 184 rgelt[i] = temp; 185 mpCurrent = mpCurrent->pNext; 186 } 187 if(pceltFetched) 188 { *pceltFetched = i; 189 } 190 191 return hr; 192 } 193 194 /************************************************************************** 195 * IEnumIDList_fnSkip 196 */ 197 HRESULT WINAPI CEnumIDListBase::Skip( 198 ULONG celt) 199 { 200 DWORD dwIndex; 201 HRESULT hr = S_OK; 202 203 TRACE("(%p)->(%u)\n", this, celt); 204 205 for(dwIndex = 0; dwIndex < celt; dwIndex++) 206 { if(!mpCurrent) 207 { hr = S_FALSE; 208 break; 209 } 210 mpCurrent = mpCurrent->pNext; 211 } 212 return hr; 213 } 214 215 /************************************************************************** 216 * IEnumIDList_fnReset 217 */ 218 HRESULT WINAPI CEnumIDListBase::Reset() 219 { 220 TRACE("(%p)\n", this); 221 mpCurrent = mpFirst; 222 return S_OK; 223 } 224 225 /************************************************************************** 226 * IEnumIDList_fnClone 227 */ 228 HRESULT WINAPI CEnumIDListBase::Clone(LPENUMIDLIST *ppenum) 229 { 230 TRACE("(%p)->() to (%p)->() E_NOTIMPL\n", this, ppenum); 231 return E_NOTIMPL; 232 } 233 234 /************************************************************************** 235 * IEnumIDList_Folder_Constructor 236 * 237 */ 238 HRESULT IEnumIDList_Constructor(IEnumIDList **enumerator) 239 { 240 return ShellObjectCreator<CEnumIDListBase>(IID_PPV_ARG(IEnumIDList, enumerator)); 241 } 242