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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/debug.h"
28 #include "undocshell.h"
35 #include "shell32_main.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
39 typedef struct tagENUMLIST
41 struct tagENUMLIST
*pNext
;
44 } ENUMLIST
, *LPENUMLIST
;
48 ICOM_VFIELD(IEnumIDList
);
56 static struct ICOM_VTABLE(IEnumIDList
) eidlvt
;
58 /**************************************************************************
61 static BOOL
AddToEnumList(
65 ICOM_THIS(IEnumIDListImpl
,iface
);
69 TRACE("(%p)->(pidl=%p)\n",This
,pidl
);
70 pNew
= (LPENUMLIST
)SHAlloc(sizeof(ENUMLIST
));
73 /*set the next pointer */
77 /*is This the first item in the list? */
81 This
->mpCurrent
= pNew
;
86 /*add the new item to the end of the list */
87 This
->mpLast
->pNext
= pNew
;
90 /*update the last item pointer */
92 TRACE("-- (%p)->(first=%p, last=%p)\n",This
,This
->mpFirst
,This
->mpLast
);
98 /**************************************************************************
99 * CreateFolderEnumList()
101 static BOOL
CreateFolderEnumList(
106 ICOM_THIS(IEnumIDListImpl
,iface
);
108 LPITEMIDLIST pidl
=NULL
;
109 WIN32_FIND_DATAA stffile
;
111 CHAR szPath
[MAX_PATH
];
113 TRACE("(%p)->(path=%s flags=0x%08lx) \n",This
,debugstr_a(lpszPath
),dwFlags
);
115 if(!lpszPath
|| !lpszPath
[0]) return FALSE
;
117 strcpy(szPath
, lpszPath
);
118 PathAddBackslashA(szPath
);
119 strcat(szPath
,"*.*");
121 /*enumerate the folders*/
122 if(dwFlags
& SHCONTF_FOLDERS
)
124 TRACE("-- (%p)-> enumerate SHCONTF_FOLDERS of %s\n",This
,debugstr_a(szPath
));
125 hFile
= FindFirstFileA(szPath
,&stffile
);
126 if ( hFile
!= INVALID_HANDLE_VALUE
)
130 if ( !(dwFlags
& SHCONTF_INCLUDEHIDDEN
) && (stffile
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) ) continue;
131 if ( (stffile
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) && strcmp (stffile
.cFileName
, ".") && strcmp (stffile
.cFileName
, ".."))
133 pidl
= _ILCreateFolder (&stffile
);
134 if(pidl
&& AddToEnumList((IEnumIDList
*)This
, pidl
))
140 } while( FindNextFileA(hFile
,&stffile
));
145 /*enumerate the non-folder items (values) */
146 if(dwFlags
& SHCONTF_NONFOLDERS
)
148 TRACE("-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n",This
,debugstr_a(szPath
));
149 hFile
= FindFirstFileA(szPath
,&stffile
);
150 if ( hFile
!= INVALID_HANDLE_VALUE
)
154 if ( !(dwFlags
& SHCONTF_INCLUDEHIDDEN
) && (stffile
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) ) continue;
155 if (! (stffile
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) )
157 pidl
= _ILCreateValue(&stffile
);
158 if(pidl
&& AddToEnumList((IEnumIDList
*)This
, pidl
))
164 } while( FindNextFileA(hFile
,&stffile
));
171 /**************************************************************************
172 * CreateDesktopEnumList()
174 static BOOL
CreateDesktopEnumList(
178 ICOM_THIS(IEnumIDListImpl
,iface
);
180 LPITEMIDLIST pidl
=NULL
;
182 char szPath
[MAX_PATH
];
184 TRACE("(%p)->(flags=0x%08lx) \n",This
,dwFlags
);
186 /*enumerate the root folders */
187 if(dwFlags
& SHCONTF_FOLDERS
)
189 /*create the pidl for This item */
190 pidl
= _ILCreateMyComputer();
193 if(!AddToEnumList((IEnumIDList
*)This
, pidl
))
197 if (! RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\desktop\\NameSpace", 0, KEY_READ
, &hkey
))
204 DWORD size
= sizeof (iid
);
206 if (ERROR_SUCCESS
!=RegEnumKeyExA(hkey
, i
, iid
, &size
, 0, NULL
, NULL
, NULL
))
209 pidl
= _ILCreateSpecial(iid
);
212 AddToEnumList((IEnumIDList
*)This
, pidl
);
220 /*enumerate the elements in %windir%\desktop */
221 SHGetSpecialFolderPathA(0, szPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
222 CreateFolderEnumList( (IEnumIDList
*)This
, szPath
, dwFlags
);
227 /**************************************************************************
228 * CreateMyCompEnumList()
230 static BOOL
CreateMyCompEnumList(
234 ICOM_THIS(IEnumIDListImpl
,iface
);
236 LPITEMIDLIST pidl
=NULL
;
241 TRACE("(%p)->(flags=0x%08lx) \n",This
,dwFlags
);
243 /*enumerate the folders*/
244 if(dwFlags
& SHCONTF_FOLDERS
)
246 dwDrivemap
= GetLogicalDrives();
247 strcpy (szDriveName
,"A:\\");
248 while (szDriveName
[0]<='Z')
250 if(dwDrivemap
& 0x00000001L
)
252 pidl
= _ILCreateDrive(szDriveName
);
255 if(!AddToEnumList((IEnumIDList
*)This
, pidl
))
260 dwDrivemap
= dwDrivemap
>> 1;
263 TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n",This
);
264 if (! RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\mycomputer\\NameSpace", 0, KEY_READ
, &hkey
))
271 DWORD size
= sizeof (iid
);
273 if (ERROR_SUCCESS
!=RegEnumKeyExA(hkey
, i
, iid
, &size
, 0, NULL
, NULL
, NULL
))
276 pidl
= _ILCreateSpecial(iid
);
279 AddToEnumList((IEnumIDList
*)This
, pidl
);
289 /**************************************************************************
292 static BOOL
DeleteList(
295 ICOM_THIS(IEnumIDListImpl
,iface
);
299 TRACE("(%p)->()\n",This
);
302 { pDelete
= This
->mpFirst
;
303 This
->mpFirst
= pDelete
->pNext
;
304 SHFree(pDelete
->pidl
);
307 This
->mpFirst
= This
->mpLast
= This
->mpCurrent
= NULL
;
311 /**************************************************************************
312 * IEnumIDList_Folder_Constructor
316 IEnumIDList
* IEnumIDList_Constructor(
321 IEnumIDListImpl
* lpeidl
;
324 TRACE("()->(%s flags=0x%08lx kind=0x%08lx)\n",debugstr_a(lpszPath
),dwFlags
, dwKind
);
326 lpeidl
= (IEnumIDListImpl
*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IEnumIDListImpl
));
331 lpeidl
->lpVtbl
= &eidlvt
;
336 ret
= CreateDesktopEnumList((IEnumIDList
*)lpeidl
, dwFlags
);
340 ret
= CreateMyCompEnumList((IEnumIDList
*)lpeidl
, dwFlags
);
344 ret
= CreateFolderEnumList((IEnumIDList
*)lpeidl
, lpszPath
, dwFlags
);
349 HeapFree(GetProcessHeap(),0,lpeidl
);
354 TRACE("-- (%p)->()\n",lpeidl
);
356 return (IEnumIDList
*)lpeidl
;
359 /**************************************************************************
360 * EnumIDList_QueryInterface
362 static HRESULT WINAPI
IEnumIDList_fnQueryInterface(
367 ICOM_THIS(IEnumIDListImpl
,iface
);
369 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
373 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
376 else if(IsEqualIID(riid
, &IID_IEnumIDList
)) /*IEnumIDList*/
377 { *ppvObj
= (IEnumIDList
*)This
;
381 { IEnumIDList_AddRef((IEnumIDList
*)*ppvObj
);
382 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
386 TRACE("-- Interface: E_NOINTERFACE\n");
387 return E_NOINTERFACE
;
390 /******************************************************************************
391 * IEnumIDList_fnAddRef
393 static ULONG WINAPI
IEnumIDList_fnAddRef(
396 ICOM_THIS(IEnumIDListImpl
,iface
);
397 TRACE("(%p)->(%lu)\n",This
,This
->ref
);
398 return ++(This
->ref
);
400 /******************************************************************************
401 * IEnumIDList_fnRelease
403 static ULONG WINAPI
IEnumIDList_fnRelease(
406 ICOM_THIS(IEnumIDListImpl
,iface
);
408 TRACE("(%p)->(%lu)\n",This
,This
->ref
);
410 if (!--(This
->ref
)) {
411 TRACE(" destroying IEnumIDList(%p)\n",This
);
412 DeleteList((IEnumIDList
*)This
);
413 HeapFree(GetProcessHeap(),0,This
);
419 /**************************************************************************
423 static HRESULT WINAPI
IEnumIDList_fnNext(
426 LPITEMIDLIST
* rgelt
,
429 ICOM_THIS(IEnumIDListImpl
,iface
);
435 TRACE("(%p)->(%ld,%p, %p)\n",This
,celt
,rgelt
,pceltFetched
);
437 /* It is valid to leave pceltFetched NULL when celt is 1. Some of explorer's
438 * subsystems actually use it (and so may a third party browser)
445 if(celt
> 1 && !pceltFetched
)
446 { return E_INVALIDARG
;
449 if(celt
> 0 && !This
->mpCurrent
)
453 for(i
= 0; i
< celt
; i
++)
454 { if(!(This
->mpCurrent
))
457 temp
= ILClone(This
->mpCurrent
->pidl
);
459 This
->mpCurrent
= This
->mpCurrent
->pNext
;
468 /**************************************************************************
471 static HRESULT WINAPI
IEnumIDList_fnSkip(
472 IEnumIDList
* iface
,ULONG celt
)
474 ICOM_THIS(IEnumIDListImpl
,iface
);
479 TRACE("(%p)->(%lu)\n",This
,celt
);
481 for(dwIndex
= 0; dwIndex
< celt
; dwIndex
++)
482 { if(!This
->mpCurrent
)
486 This
->mpCurrent
= This
->mpCurrent
->pNext
;
490 /**************************************************************************
491 * IEnumIDList_fnReset
493 static HRESULT WINAPI
IEnumIDList_fnReset(
496 ICOM_THIS(IEnumIDListImpl
,iface
);
498 TRACE("(%p)\n",This
);
499 This
->mpCurrent
= This
->mpFirst
;
502 /**************************************************************************
503 * IEnumIDList_fnClone
505 static HRESULT WINAPI
IEnumIDList_fnClone(
506 IEnumIDList
* iface
,LPENUMIDLIST
* ppenum
)
508 ICOM_THIS(IEnumIDListImpl
,iface
);
510 TRACE("(%p)->() to (%p)->() E_NOTIMPL\n",This
,ppenum
);
514 /**************************************************************************
515 * IEnumIDList_fnVTable
517 static ICOM_VTABLE (IEnumIDList
) eidlvt
=
519 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
520 IEnumIDList_fnQueryInterface
,
521 IEnumIDList_fnAddRef
,
522 IEnumIDList_fnRelease
,