[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 /**************************************************************************
127 * IEnumIDList_fnNext
128 */
129
130 HRESULT WINAPI CEnumIDListBase::Next(
131 ULONG celt,
132 LPITEMIDLIST * rgelt,
133 ULONG *pceltFetched)
134 {
135 ULONG i;
136 HRESULT hr = S_OK;
137 LPITEMIDLIST temp;
138
139 TRACE("(%p)->(%d,%p, %p)\n", this, celt, rgelt, pceltFetched);
140
141 /* It is valid to leave pceltFetched NULL when celt is 1. Some of explorer's
142 * subsystems actually use it (and so may a third party browser)
143 */
144 if(pceltFetched)
145 *pceltFetched = 0;
146
147 *rgelt=0;
148
149 if(celt > 1 && !pceltFetched)
150 { return E_INVALIDARG;
151 }
152
153 if(celt > 0 && !mpCurrent)
154 { return S_FALSE;
155 }
156
157 for(i = 0; i < celt; i++)
158 { if(!mpCurrent)
159 break;
160
161 temp = ILClone(mpCurrent->pidl);
162 rgelt[i] = temp;
163 mpCurrent = mpCurrent->pNext;
164 }
165 if(pceltFetched)
166 { *pceltFetched = i;
167 }
168
169 return hr;
170 }
171
172 /**************************************************************************
173 * IEnumIDList_fnSkip
174 */
175 HRESULT WINAPI CEnumIDListBase::Skip(
176 ULONG celt)
177 {
178 DWORD dwIndex;
179 HRESULT hr = S_OK;
180
181 TRACE("(%p)->(%u)\n", this, celt);
182
183 for(dwIndex = 0; dwIndex < celt; dwIndex++)
184 { if(!mpCurrent)
185 { hr = S_FALSE;
186 break;
187 }
188 mpCurrent = mpCurrent->pNext;
189 }
190 return hr;
191 }
192
193 /**************************************************************************
194 * IEnumIDList_fnReset
195 */
196 HRESULT WINAPI CEnumIDListBase::Reset()
197 {
198 TRACE("(%p)\n", this);
199 mpCurrent = mpFirst;
200 return S_OK;
201 }
202
203 /**************************************************************************
204 * IEnumIDList_fnClone
205 */
206 HRESULT WINAPI CEnumIDListBase::Clone(LPENUMIDLIST *ppenum)
207 {
208 TRACE("(%p)->() to (%p)->() E_NOTIMPL\n", this, ppenum);
209 return E_NOTIMPL;
210 }
211
212 /**************************************************************************
213 * IEnumIDList_Folder_Constructor
214 *
215 */
216 HRESULT IEnumIDList_Constructor(IEnumIDList **enumerator)
217 {
218 return ShellObjectCreator<CEnumIDListBase>(IID_PPV_ARG(IEnumIDList, enumerator));
219 }