4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
14 #include "interfaces.h"
22 #include "shell32_main.h"
24 /* IEnumIDList Implementation */
25 static HRESULT WINAPI IEnumIDList_QueryInterface(LPENUMIDLIST,REFIID,LPVOID*);
26 static ULONG WINAPI IEnumIDList_AddRef(LPENUMIDLIST);
27 static ULONG WINAPI IEnumIDList_Release(LPENUMIDLIST);
28 static HRESULT WINAPI IEnumIDList_Next(LPENUMIDLIST,ULONG,LPITEMIDLIST*,ULONG*);
29 static HRESULT WINAPI IEnumIDList_Skip(LPENUMIDLIST,ULONG);
30 static HRESULT WINAPI IEnumIDList_Reset(LPENUMIDLIST);
31 static HRESULT WINAPI IEnumIDList_Clone(LPENUMIDLIST,LPENUMIDLIST*);
32 static BOOL32 WINAPI IEnumIDList_CreateEnumList(LPENUMIDLIST,LPCSTR, DWORD);
33 static BOOL32 WINAPI IEnumIDList_AddToEnumList(LPENUMIDLIST,LPITEMIDLIST);
34 static BOOL32 WINAPI IEnumIDList_DeleteList(LPENUMIDLIST);
36 /**************************************************************************
39 static IEnumIDList_VTable eidlvt =
40 { IEnumIDList_QueryInterface,
47 IEnumIDList_CreateEnumList,
48 IEnumIDList_AddToEnumList,
49 IEnumIDList_DeleteList
52 /**************************************************************************
53 * IEnumIDList_Constructor
56 LPENUMIDLIST IEnumIDList_Constructor( LPCSTR lpszPath, DWORD dwFlags)
57 { LPENUMIDLIST lpeidl;
59 lpeidl = (LPENUMIDLIST)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumIDList));
64 lpeidl->lpvtbl = &eidlvt;
67 lpeidl->mpCurrent=NULL;
69 TRACE(shell,"(%p)->(%s flags=0x%08lx)\n",lpeidl,debugstr_a(lpszPath),dwFlags);
71 if(!IEnumIDList_CreateEnumList(lpeidl, lpszPath, dwFlags))
73 { HeapFree(GetProcessHeap(),0,lpeidl);
78 TRACE(shell,"-- (%p)->()\n",lpeidl);
82 /**************************************************************************
83 * EnumIDList::QueryInterface
85 static HRESULT WINAPI IEnumIDList_QueryInterface(
86 LPENUMIDLIST this, REFIID riid, LPVOID *ppvObj)
88 WINE_StringFromCLSID((LPCLSID)riid,xriid);
89 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
93 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
96 else if(IsEqualIID(riid, &IID_IEnumIDList)) /*IEnumIDList*/
97 { *ppvObj = (IEnumIDList*)this;
101 { (*(LPENUMIDLIST*)ppvObj)->lpvtbl->fnAddRef(this);
102 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
105 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
106 return E_NOINTERFACE;
109 /******************************************************************************
112 static ULONG WINAPI IEnumIDList_AddRef(LPENUMIDLIST this)
113 { TRACE(shell,"(%p)->()\n",this);
114 return ++(this->ref);
116 /******************************************************************************
117 * IEnumIDList_Release
119 static ULONG WINAPI IEnumIDList_Release(LPENUMIDLIST this)
120 { TRACE(shell,"(%p)->()\n",this);
122 { TRACE(shell," destroying IEnumIDList(%p)\n",this);
123 IEnumIDList_DeleteList(this);
124 HeapFree(GetProcessHeap(),0,this);
130 /**************************************************************************
134 static HRESULT WINAPI IEnumIDList_Next(
135 LPENUMIDLIST this,ULONG celt,LPITEMIDLIST * rgelt,ULONG *pceltFetched)
140 TRACE(shell,"(%p)->(%ld,%p, %p)\n",this,celt,rgelt,pceltFetched);
142 /* It is valid to leave pceltFetched NULL when celt is 1. Some of explorer's
143 * subsystems actually use it (and so may a third party browser)
150 if(celt > 1 && !pceltFetched)
151 { return E_INVALIDARG;
154 for(i = 0; i < celt; i++)
155 { if(!(this->mpCurrent))
159 temp = ILClone(this->mpCurrent->pidl);
161 this->mpCurrent = this->mpCurrent->pNext;
170 /**************************************************************************
173 static HRESULT WINAPI IEnumIDList_Skip(
174 LPENUMIDLIST this,ULONG celt)
178 TRACE(shell,"(%p)->(%lu)\n",this,celt);
180 for(dwIndex = 0; dwIndex < celt; dwIndex++)
181 { if(!this->mpCurrent)
185 this->mpCurrent = this->mpCurrent->pNext;
189 /**************************************************************************
192 static HRESULT WINAPI IEnumIDList_Reset(LPENUMIDLIST this)
193 { TRACE(shell,"(%p)\n",this);
194 this->mpCurrent = this->mpFirst;
197 /**************************************************************************
200 static HRESULT WINAPI IEnumIDList_Clone(
201 LPENUMIDLIST this,LPENUMIDLIST * ppenum)
202 { TRACE(shell,"(%p)->() to (%p)->() E_NOTIMPL\n",this,ppenum);
205 /**************************************************************************
206 * EnumIDList_CreateEnumList()
207 * fixme: devices not handled
208 * fixme: add wildcards to path
210 static BOOL32 WINAPI IEnumIDList_CreateEnumList(LPENUMIDLIST this, LPCSTR lpszPath, DWORD dwFlags)
211 { LPITEMIDLIST pidl=NULL;
212 LPPIDLDATA pData=NULL;
213 WIN32_FIND_DATA32A stffile;
217 CHAR szPath[MAX_PATH];
219 TRACE(shell,"(%p)->(path=%s flags=0x%08lx) \n",this,debugstr_a(lpszPath),dwFlags);
221 if (lpszPath && lpszPath[0]!='\0')
222 { strcpy(szPath, lpszPath);
223 PathAddBackslash32A(szPath);
224 strcat(szPath,"*.*");
227 /*enumerate the folders*/
228 if(dwFlags & SHCONTF_FOLDERS)
229 { /* special case - we can't enumerate the Desktop level Objects (MyComputer,Nethood...
230 so we need to fake an enumeration of those.*/
232 { TRACE (shell,"-- (%p)-> enumerate SHCONTF_FOLDERS (special) items\n",this);
233 //create the pidl for this item
234 pidl = _ILCreateMyComputer();
236 { pData = _ILGetDataPointer(pidl);
237 pData->u.generic.dwSFGAO = SFGAO_HASPROPSHEET | SFGAO_READONLY | SFGAO_HASSUBFOLDER;
238 if(!IEnumIDList_AddToEnumList(this, pidl))
242 else if (lpszPath[0]=='\0') /* enumerate the drives*/
243 { TRACE (shell,"-- (%p)-> enumerate SHCONTF_FOLDERS (drives)\n",this);
244 dwDrivemap = GetLogicalDrives();
245 strcpy (szDriveName,"A:\\");
246 while (szDriveName[0]<='Z')
247 { if(dwDrivemap & 0x00000001L)
248 { pidl = _ILCreateDrive(szDriveName);
249 pData = _ILGetDataPointer(pidl);
250 pData->u.drive.dwSFGAO = SFGAO_HASPROPSHEET | SFGAO_READONLY | SFGAO_CANLINK |
251 SFGAO_HASSUBFOLDER | SFGAO_DROPTARGET | SFGAO_FILESYSTEM;
253 { if(!IEnumIDList_AddToEnumList(this, pidl))
258 dwDrivemap = dwDrivemap >> 1;
262 { TRACE (shell,"-- (%p)-> enumerate SHCONTF_FOLDERS of %s\n",this,debugstr_a(szPath));
263 hFile = FindFirstFile32A(szPath,&stffile);
264 if ( hFile != INVALID_HANDLE_VALUE32 )
266 { if ( (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strcmp (stffile.cFileName, ".") && strcmp (stffile.cFileName, ".."))
267 { pidl = _ILCreateFolder( stffile.cFileName);
269 { pData = _ILGetDataPointer(pidl);
270 pData->u.folder.dwSFGAO = SFGAO_CANCOPY | SFGAO_CANDELETE | SFGAO_CANLINK |
271 SFGAO_CANMOVE | SFGAO_CANRENAME | SFGAO_DROPTARGET |
272 SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER;
273 if ( stffile.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
274 { pData->u.folder.dwSFGAO |= SFGAO_READONLY;
276 FileTimeToDosDateTime(&stffile.ftLastWriteTime,&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
277 pData->u.folder.dwFileSize = stffile.nFileSizeLow;
278 pData->u.folder.uFileAttribs=stffile.dwFileAttributes;
279 strncpy (pData->u.folder.szAlternateName, stffile.cAlternateFileName,14);
280 if(!IEnumIDList_AddToEnumList(this, pidl))
288 } while( FindNextFile32A(hFile,&stffile));
293 //enumerate the non-folder items (values)
294 if(dwFlags & SHCONTF_NONFOLDERS)
296 { TRACE (shell,"-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n",this,debugstr_a(szPath));
297 hFile = FindFirstFile32A(szPath,&stffile);
298 if ( hFile != INVALID_HANDLE_VALUE32 )
300 { if (! (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
301 { pidl = _ILCreateValue( stffile.cFileName);
303 { pData = _ILGetDataPointer(pidl);
304 pData->u.file.dwSFGAO = SFGAO_CANCOPY | SFGAO_CANDELETE | SFGAO_CANLINK |
305 SFGAO_CANMOVE | SFGAO_CANRENAME | SFGAO_DROPTARGET |
306 SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM;
307 if ( stffile.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
308 { pData->u.file.dwSFGAO |= SFGAO_READONLY;
310 FileTimeToDosDateTime(&stffile.ftLastWriteTime,&pData->u.file.uFileDate,&pData->u.file.uFileTime);
311 pData->u.file.dwFileSize = stffile.nFileSizeLow;
312 pData->u.file.uFileAttribs=stffile.dwFileAttributes;
313 strncpy (pData->u.file.szAlternateName, stffile.cAlternateFileName,14);
314 if(!IEnumIDList_AddToEnumList(this, pidl))
322 } while( FindNextFile32A(hFile,&stffile));
330 /**************************************************************************
331 * EnumIDList_AddToEnumList()
333 static BOOL32 WINAPI IEnumIDList_AddToEnumList(LPENUMIDLIST this,LPITEMIDLIST pidl)
336 TRACE(shell,"(%p)->(pidl=%p)\n",this,pidl);
337 pNew = (LPENUMLIST)SHAlloc(sizeof(ENUMLIST));
339 { //set the next pointer
343 //is this the first item in the list?
345 { this->mpFirst = pNew;
346 this->mpCurrent = pNew;
350 { //add the new item to the end of the list
351 this->mpLast->pNext = pNew;
354 //update the last item pointer
356 TRACE(shell,"-- (%p)->(first=%p, last=%p)\n",this,this->mpFirst,this->mpLast);
361 /**************************************************************************
362 * EnumIDList_DeleteList()
364 static BOOL32 WINAPI IEnumIDList_DeleteList(LPENUMIDLIST this)
365 { LPENUMLIST pDelete;
367 TRACE(shell,"(%p)->()\n",this);
370 { pDelete = this->mpFirst;
371 this->mpFirst = pDelete->pNext;
372 SHFree(pDelete->pidl);
375 this->mpFirst = this->mpLast = this->mpCurrent = NULL;