[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / CEnumIDListBase.cpp
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 }