Reactos
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
23WINE_DEFAULT_DEBUG_CHANNEL(shell);
24
25CEnumIDListBase::CEnumIDListBase() :
26 mpFirst(NULL),
27 mpLast(NULL),
28 mpCurrent(NULL)
29{
30}
31
32CEnumIDListBase::~CEnumIDListBase()
33{
34 DeleteList();
35}
36
37/**************************************************************************
38 * AddToEnumList()
39 */
40BOOL 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*/
80BOOL 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
99HRESULT 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
119HRESULT 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*/
170HRESULT 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*/
191HRESULT WINAPI CEnumIDListBase::Reset()
192{
193 TRACE("(%p)\n", this);
194 mpCurrent = mpFirst;
195 return S_OK;
196}
197
198/**************************************************************************
199* IEnumIDList_fnClone
200*/
201HRESULT 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 */
211HRESULT IEnumIDList_Constructor(IEnumIDList **enumerator)
212{
213 return ShellObjectCreator<CEnumIDListBase>(IID_PPV_ARG(IEnumIDList, enumerator));
214}