shell32: Return the IEnumIDList object on its creation.
[wine/multimedia.git] / dlls / shell32 / enumidlist.c
blob9e43ed45412fe60df9b2578bddd60d928317c70f
1 /*
2 * IEnumIDList
4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
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.
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.
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
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #define COBJMACROS
27 #include "wine/debug.h"
28 #include "wine/unicode.h"
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winreg.h"
32 #include "shlwapi.h"
34 #include "pidl.h"
35 #include "shell32_main.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(shell);
39 /**************************************************************************
40 * AddToEnumList()
42 BOOL AddToEnumList(
43 IEnumIDList * iface,
44 LPITEMIDLIST pidl)
46 IEnumIDListImpl *This = (IEnumIDListImpl *)iface;
48 struct enumlist *pNew;
50 TRACE("(%p)->(pidl=%p)\n",This,pidl);
52 if (!iface || !pidl)
53 return FALSE;
55 pNew = SHAlloc(sizeof(*pNew));
56 if(pNew)
58 /*set the next pointer */
59 pNew->pNext = NULL;
60 pNew->pidl = pidl;
62 /*is This the first item in the list? */
63 if(!This->mpFirst)
65 This->mpFirst = pNew;
66 This->mpCurrent = pNew;
69 if(This->mpLast)
71 /*add the new item to the end of the list */
72 This->mpLast->pNext = pNew;
75 /*update the last item pointer */
76 This->mpLast = pNew;
77 TRACE("-- (%p)->(first=%p, last=%p)\n",This,This->mpFirst,This->mpLast);
78 return TRUE;
80 return FALSE;
83 /**************************************************************************
84 * CreateFolderEnumList()
86 BOOL CreateFolderEnumList(
87 IEnumIDList *list,
88 LPCWSTR lpszPath,
89 DWORD dwFlags)
91 LPITEMIDLIST pidl=NULL;
92 WIN32_FIND_DATAW stffile;
93 HANDLE hFile;
94 WCHAR szPath[MAX_PATH];
95 BOOL succeeded = TRUE;
96 static const WCHAR stars[] = { '*','.','*',0 };
97 static const WCHAR dot[] = { '.',0 };
98 static const WCHAR dotdot[] = { '.','.',0 };
100 TRACE("(%p)->(path=%s flags=0x%08x)\n", list, debugstr_w(lpszPath), dwFlags);
102 if(!lpszPath || !lpszPath[0]) return FALSE;
104 strcpyW(szPath, lpszPath);
105 PathAddBackslashW(szPath);
106 strcatW(szPath,stars);
108 hFile = FindFirstFileW(szPath,&stffile);
109 if ( hFile != INVALID_HANDLE_VALUE )
111 BOOL findFinished = FALSE;
115 if ( !(stffile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
116 || (dwFlags & SHCONTF_INCLUDEHIDDEN) )
118 if ( (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
119 dwFlags & SHCONTF_FOLDERS &&
120 strcmpW(stffile.cFileName, dot) && strcmpW(stffile.cFileName, dotdot))
122 pidl = _ILCreateFromFindDataW(&stffile);
123 succeeded = succeeded && AddToEnumList(list, pidl);
125 else if (!(stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
126 && dwFlags & SHCONTF_NONFOLDERS)
128 pidl = _ILCreateFromFindDataW(&stffile);
129 succeeded = succeeded && AddToEnumList(list, pidl);
132 if (succeeded)
134 if (!FindNextFileW(hFile, &stffile))
136 if (GetLastError() == ERROR_NO_MORE_FILES)
137 findFinished = TRUE;
138 else
139 succeeded = FALSE;
142 } while (succeeded && !findFinished);
143 FindClose(hFile);
145 return succeeded;
148 static BOOL DeleteList(IEnumIDListImpl *This)
150 struct enumlist *pDelete;
152 TRACE("(%p)->()\n",This);
154 while(This->mpFirst)
155 { pDelete = This->mpFirst;
156 This->mpFirst = pDelete->pNext;
157 SHFree(pDelete->pidl);
158 SHFree(pDelete);
160 This->mpFirst = This->mpLast = This->mpCurrent = NULL;
161 return TRUE;
164 static inline IEnumIDListImpl *impl_from_IEnumIDList(IEnumIDList *iface)
166 return CONTAINING_RECORD(iface, IEnumIDListImpl, IEnumIDList_iface);
169 /**************************************************************************
170 * IEnumIDList::QueryInterface
172 static HRESULT WINAPI IEnumIDList_fnQueryInterface(IEnumIDList *iface, REFIID riid, void **ppvObj)
174 IEnumIDListImpl *This = impl_from_IEnumIDList(iface);
176 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
178 *ppvObj = NULL;
180 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
181 { *ppvObj = This;
183 else if(IsEqualIID(riid, &IID_IEnumIDList)) /*IEnumIDList*/
184 { *ppvObj = This;
187 if(*ppvObj)
188 { IEnumIDList_AddRef((IEnumIDList*)*ppvObj);
189 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
190 return S_OK;
193 TRACE("-- Interface: E_NOINTERFACE\n");
194 return E_NOINTERFACE;
197 /******************************************************************************
198 * IEnumIDList::AddRef
200 static ULONG WINAPI IEnumIDList_fnAddRef(IEnumIDList *iface)
202 IEnumIDListImpl *This = impl_from_IEnumIDList(iface);
203 ULONG refCount = InterlockedIncrement(&This->ref);
205 TRACE("(%p)->(%u)\n", This, refCount - 1);
207 return refCount;
209 /******************************************************************************
210 * IEnumIDList::Release
212 static ULONG WINAPI IEnumIDList_fnRelease(IEnumIDList *iface)
214 IEnumIDListImpl *This = impl_from_IEnumIDList(iface);
215 ULONG refCount = InterlockedDecrement(&This->ref);
217 TRACE("(%p)->(%u)\n", This, refCount + 1);
219 if (!refCount) {
220 TRACE(" destroying IEnumIDList(%p)\n",This);
221 DeleteList(This);
222 HeapFree(GetProcessHeap(),0,This);
224 return refCount;
227 /**************************************************************************
228 * IEnumIDList::Next
231 static HRESULT WINAPI IEnumIDList_fnNext(IEnumIDList *iface, ULONG celt, LPITEMIDLIST *rgelt,
232 ULONG *pceltFetched)
234 IEnumIDListImpl *This = impl_from_IEnumIDList(iface);
236 ULONG i;
237 HRESULT hr = S_OK;
238 LPITEMIDLIST temp;
240 TRACE("(%p)->(%d,%p, %p)\n",This,celt,rgelt,pceltFetched);
242 /* It is valid to leave pceltFetched NULL when celt is 1. Some of explorer's
243 * subsystems actually use it (and so may a third party browser)
245 if(pceltFetched)
246 *pceltFetched = 0;
248 *rgelt=0;
250 if(celt > 1 && !pceltFetched)
251 { return E_INVALIDARG;
254 if(celt > 0 && !This->mpCurrent)
255 { return S_FALSE;
258 for(i = 0; i < celt; i++)
259 { if(!(This->mpCurrent))
260 break;
262 temp = ILClone(This->mpCurrent->pidl);
263 rgelt[i] = temp;
264 This->mpCurrent = This->mpCurrent->pNext;
266 if(pceltFetched)
267 { *pceltFetched = i;
270 return hr;
273 /**************************************************************************
274 * IEnumIDList::Skip
276 static HRESULT WINAPI IEnumIDList_fnSkip(IEnumIDList *iface, ULONG celt)
278 IEnumIDListImpl *This = impl_from_IEnumIDList(iface);
280 DWORD dwIndex;
281 HRESULT hr = S_OK;
283 TRACE("(%p)->(%u)\n",This,celt);
285 for(dwIndex = 0; dwIndex < celt; dwIndex++)
286 { if(!This->mpCurrent)
287 { hr = S_FALSE;
288 break;
290 This->mpCurrent = This->mpCurrent->pNext;
292 return hr;
294 /**************************************************************************
295 * IEnumIDList::Reset
297 static HRESULT WINAPI IEnumIDList_fnReset(IEnumIDList *iface)
299 IEnumIDListImpl *This = impl_from_IEnumIDList(iface);
301 TRACE("(%p)\n",This);
302 This->mpCurrent = This->mpFirst;
303 return S_OK;
305 /**************************************************************************
306 * IEnumIDList::Clone
308 static HRESULT WINAPI IEnumIDList_fnClone(IEnumIDList *iface, IEnumIDList **ppenum)
310 IEnumIDListImpl *This = impl_from_IEnumIDList(iface);
312 TRACE("(%p)->() to (%p)->() E_NOTIMPL\n",This,ppenum);
313 return E_NOTIMPL;
316 static const IEnumIDListVtbl eidlvt =
318 IEnumIDList_fnQueryInterface,
319 IEnumIDList_fnAddRef,
320 IEnumIDList_fnRelease,
321 IEnumIDList_fnNext,
322 IEnumIDList_fnSkip,
323 IEnumIDList_fnReset,
324 IEnumIDList_fnClone,
327 IEnumIDListImpl *IEnumIDList_Constructor(void)
329 IEnumIDListImpl *lpeidl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*lpeidl));
331 if (lpeidl)
333 lpeidl->ref = 1;
334 lpeidl->IEnumIDList_iface.lpVtbl = &eidlvt;
337 TRACE("-- (%p)->()\n",lpeidl);
339 return lpeidl;