4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
10 #include "wine/obj_base.h"
11 #include "wine/obj_enumidlist.h"
16 #include "shell32_main.h"
18 DEFAULT_DEBUG_CHANNEL(shell)
20 typedef struct tagENUMLIST
22 struct tagENUMLIST *pNext;
25 } ENUMLIST, *LPENUMLIST;
29 ICOM_VTABLE(IEnumIDList)* lpvtbl;
37 static struct ICOM_VTABLE(IEnumIDList) eidlvt;
39 /**************************************************************************
40 * IEnumIDList_fnConstructor
43 IEnumIDList * IEnumIDList_Constructor(
46 { IEnumIDListImpl* lpeidl;
48 lpeidl = (IEnumIDListImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumIDListImpl));
53 lpeidl->lpvtbl = &eidlvt;
56 lpeidl->mpCurrent=NULL;
58 TRACE(shell,"(%p)->(%s flags=0x%08lx)\n",lpeidl,debugstr_a(lpszPath),dwFlags);
60 if(!IEnumIDList_CreateEnumList((IEnumIDList*)lpeidl, lpszPath, dwFlags))
62 { HeapFree(GetProcessHeap(),0,lpeidl);
67 TRACE(shell,"-- (%p)->()\n",lpeidl);
69 return (IEnumIDList*)lpeidl;
72 /**************************************************************************
73 * EnumIDList_QueryInterface
75 static HRESULT WINAPI IEnumIDList_fnQueryInterface(
80 ICOM_THIS(IEnumIDListImpl,iface);
83 WINE_StringFromCLSID((LPCLSID)riid,xriid);
84 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
88 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
91 else if(IsEqualIID(riid, &IID_IEnumIDList)) /*IEnumIDList*/
92 { *ppvObj = (IEnumIDList*)This;
96 { IEnumIDList_AddRef((IEnumIDList*)*ppvObj);
97 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
101 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
102 return E_NOINTERFACE;
105 /******************************************************************************
106 * IEnumIDList_fnAddRef
108 static ULONG WINAPI IEnumIDList_fnAddRef(
111 ICOM_THIS(IEnumIDListImpl,iface);
113 TRACE(shell,"(%p)->(%lu)\n",This,This->ref);
116 return ++(This->ref);
118 /******************************************************************************
119 * IEnumIDList_fnRelease
121 static ULONG WINAPI IEnumIDList_fnRelease(
124 ICOM_THIS(IEnumIDListImpl,iface);
126 TRACE(shell,"(%p)->(%lu)\n",This,This->ref);
131 { TRACE(shell," destroying IEnumIDList(%p)\n",This);
132 IEnumIDList_DeleteList((IEnumIDList*)This);
133 HeapFree(GetProcessHeap(),0,This);
139 /**************************************************************************
143 static HRESULT WINAPI IEnumIDList_fnNext(
146 LPITEMIDLIST * rgelt,
149 ICOM_THIS(IEnumIDListImpl,iface);
155 TRACE(shell,"(%p)->(%ld,%p, %p)\n",This,celt,rgelt,pceltFetched);
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)
165 if(celt > 1 && !pceltFetched)
166 { return E_INVALIDARG;
169 for(i = 0; i < celt; i++)
170 { if(!(This->mpCurrent))
174 temp = ILClone(This->mpCurrent->pidl);
176 This->mpCurrent = This->mpCurrent->pNext;
185 /**************************************************************************
188 static HRESULT WINAPI IEnumIDList_fnSkip(
189 IEnumIDList * iface,ULONG celt)
191 ICOM_THIS(IEnumIDListImpl,iface);
196 TRACE(shell,"(%p)->(%lu)\n",This,celt);
198 for(dwIndex = 0; dwIndex < celt; dwIndex++)
199 { if(!This->mpCurrent)
203 This->mpCurrent = This->mpCurrent->pNext;
207 /**************************************************************************
208 * IEnumIDList_fnReset
210 static HRESULT WINAPI IEnumIDList_fnReset(
213 ICOM_THIS(IEnumIDListImpl,iface);
215 TRACE(shell,"(%p)\n",This);
216 This->mpCurrent = This->mpFirst;
219 /**************************************************************************
220 * IEnumIDList_fnClone
222 static HRESULT WINAPI IEnumIDList_fnClone(
223 IEnumIDList * iface,LPENUMIDLIST * ppenum)
225 ICOM_THIS(IEnumIDListImpl,iface);
227 TRACE(shell,"(%p)->() to (%p)->() E_NOTIMPL\n",This,ppenum);
230 /**************************************************************************
231 * EnumIDList_CreateEnumList()
232 * fixme: devices not handled
233 * fixme: add wildcards to path
235 static BOOL WINAPI IEnumIDList_fnCreateEnumList(
240 ICOM_THIS(IEnumIDListImpl,iface);
242 LPITEMIDLIST pidl=NULL;
243 LPPIDLDATA pData=NULL;
244 WIN32_FIND_DATAA stffile;
248 CHAR szPath[MAX_PATH];
250 TRACE(shell,"(%p)->(path=%s flags=0x%08lx) \n",This,debugstr_a(lpszPath),dwFlags);
252 if (lpszPath && lpszPath[0]!='\0')
253 { strcpy(szPath, lpszPath);
254 PathAddBackslashA(szPath);
255 strcat(szPath,"*.*");
258 /*enumerate the folders*/
259 if(dwFlags & SHCONTF_FOLDERS)
260 { /* special case - we can't enumerate the Desktop level Objects (MyComputer,Nethood...
261 so we need to fake an enumeration of those.*/
263 { TRACE (shell,"-- (%p)-> enumerate SHCONTF_FOLDERS (special) items\n",This);
264 /*create the pidl for This item */
265 pidl = _ILCreateMyComputer();
267 { if(!IEnumIDList_AddToEnumList((IEnumIDList*)This, pidl))
271 else if (lpszPath[0]=='\0') /* enumerate the drives*/
272 { TRACE (shell,"-- (%p)-> enumerate SHCONTF_FOLDERS (drives)\n",This);
273 dwDrivemap = GetLogicalDrives();
274 strcpy (szDriveName,"A:\\");
275 while (szDriveName[0]<='Z')
276 { if(dwDrivemap & 0x00000001L)
277 { pidl = _ILCreateDrive(szDriveName);
279 { if(!IEnumIDList_AddToEnumList((IEnumIDList*)This, pidl))
284 dwDrivemap = dwDrivemap >> 1;
288 { TRACE (shell,"-- (%p)-> enumerate SHCONTF_FOLDERS of %s\n",This,debugstr_a(szPath));
289 hFile = FindFirstFileA(szPath,&stffile);
290 if ( hFile != INVALID_HANDLE_VALUE )
292 { if ( (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strcmp (stffile.cFileName, ".") && strcmp (stffile.cFileName, ".."))
293 { pidl = _ILCreateFolder( stffile.cAlternateFileName, stffile.cFileName);
295 { pData = _ILGetDataPointer(pidl);
296 FileTimeToDosDateTime(&stffile.ftLastWriteTime,&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
297 pData->u.folder.dwFileSize = stffile.nFileSizeLow;
298 pData->u.folder.uFileAttribs=stffile.dwFileAttributes;
299 if(!IEnumIDList_AddToEnumList((IEnumIDList*)This, pidl))
307 } while( FindNextFileA(hFile,&stffile));
312 /*enumerate the non-folder items (values) */
313 if(dwFlags & SHCONTF_NONFOLDERS)
315 { TRACE (shell,"-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n",This,debugstr_a(szPath));
316 hFile = FindFirstFileA(szPath,&stffile);
317 if ( hFile != INVALID_HANDLE_VALUE )
319 { if (! (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
320 { pidl = _ILCreateValue( stffile.cAlternateFileName, stffile.cFileName);
322 { pData = _ILGetDataPointer(pidl);
323 FileTimeToDosDateTime(&stffile.ftLastWriteTime,&pData->u.file.uFileDate,&pData->u.file.uFileTime);
324 pData->u.file.dwFileSize = stffile.nFileSizeLow;
325 pData->u.file.uFileAttribs=stffile.dwFileAttributes;
326 if(!IEnumIDList_AddToEnumList((IEnumIDList*)This, pidl))
334 } while( FindNextFileA(hFile,&stffile));
342 /**************************************************************************
343 * EnumIDList_AddToEnumList()
345 static BOOL WINAPI IEnumIDList_fnAddToEnumList(
349 ICOM_THIS(IEnumIDListImpl,iface);
353 TRACE(shell,"(%p)->(pidl=%p)\n",This,pidl);
354 pNew = (LPENUMLIST)SHAlloc(sizeof(ENUMLIST));
356 { /*set the next pointer */
360 /*is This the first item in the list? */
362 { This->mpFirst = pNew;
363 This->mpCurrent = pNew;
367 { /*add the new item to the end of the list */
368 This->mpLast->pNext = pNew;
371 /*update the last item pointer */
373 TRACE(shell,"-- (%p)->(first=%p, last=%p)\n",This,This->mpFirst,This->mpLast);
378 /**************************************************************************
379 * EnumIDList_DeleteList()
381 static BOOL WINAPI IEnumIDList_fnDeleteList(
384 ICOM_THIS(IEnumIDListImpl,iface);
388 TRACE(shell,"(%p)->()\n",This);
391 { pDelete = This->mpFirst;
392 This->mpFirst = pDelete->pNext;
393 SHFree(pDelete->pidl);
396 This->mpFirst = This->mpLast = This->mpCurrent = NULL;
400 /**************************************************************************
401 * IEnumIDList_fnVTable
403 static ICOM_VTABLE (IEnumIDList) eidlvt =
404 { IEnumIDList_fnQueryInterface,
405 IEnumIDList_fnAddRef,
406 IEnumIDList_fnRelease,
411 IEnumIDList_fnCreateEnumList,
412 IEnumIDList_fnAddToEnumList,
413 IEnumIDList_fnDeleteList