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 PathAddBackslash(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
;