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 break; 176 177 temp = ILClone(mpCurrent->pidl); 178 rgelt[i] = temp; 179 mpCurrent = mpCurrent->pNext; 180 } 181 if(pceltFetched) 182 { *pceltFetched = i; 183 } 184 185 return hr; 186 } 187 188 /************************************************************************** 189 * IEnumIDList_fnSkip 190 */ 191 HRESULT WINAPI CEnumIDListBase::Skip( 192 ULONG celt) 193 { 194 DWORD dwIndex; 195 HRESULT hr = S_OK; 196 197 TRACE("(%p)->(%u)\n", this, celt); 198 199 for(dwIndex = 0; dwIndex < celt; dwIndex++) 200 { if(!mpCurrent) 201 { hr = S_FALSE; 202 break; 203 } 204 mpCurrent = mpCurrent->pNext; 205 } 206 return hr; 207 } 208 209 /************************************************************************** 210 * IEnumIDList_fnReset 211 */ 212 HRESULT WINAPI CEnumIDListBase::Reset() 213 { 214 TRACE("(%p)\n", this); 215 mpCurrent = mpFirst; 216 return S_OK; 217 } 218 219 /************************************************************************** 220 * IEnumIDList_fnClone 221 */ 222 HRESULT WINAPI CEnumIDListBase::Clone(LPENUMIDLIST *ppenum) 223 { 224 TRACE("(%p)->() to (%p)->() E_NOTIMPL\n", this, ppenum); 225 return E_NOTIMPL; 226 } 227 228 /************************************************************************** 229 * IEnumIDList_Folder_Constructor 230 * 231 */ 232 HRESULT IEnumIDList_Constructor(IEnumIDList **enumerator) 233 { 234 return ShellObjectCreator<CEnumIDListBase>(IID_PPV_ARG(IEnumIDList, enumerator)); 235 } 236