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"
36 #include "shell32_main.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
41 typedef struct tagENUMLIST
43 struct tagENUMLIST
*pNext
;
46 } ENUMLIST
, *LPENUMLIST
;
50 ICOM_VFIELD(IEnumIDList
);
58 static struct ICOM_VTABLE(IEnumIDList
) eidlvt
;
60 /**************************************************************************
63 static BOOL
AddToEnumList(
67 ICOM_THIS(IEnumIDListImpl
,iface
);
71 TRACE("(%p)->(pidl=%p)\n",This
,pidl
);
72 pNew
= (LPENUMLIST
)SHAlloc(sizeof(ENUMLIST
));
75 /*set the next pointer */
79 /*is This the first item in the list? */
83 This
->mpCurrent
= pNew
;
88 /*add the new item to the end of the list */
89 This
->mpLast
->pNext
= pNew
;
92 /*update the last item pointer */
94 TRACE("-- (%p)->(first=%p, last=%p)\n",This
,This
->mpFirst
,This
->mpLast
);
100 /**************************************************************************
101 * CreateFolderEnumList()
103 static BOOL
CreateFolderEnumList(
108 ICOM_THIS(IEnumIDListImpl
,iface
);
110 LPITEMIDLIST pidl
=NULL
;
111 WIN32_FIND_DATAA stffile
;
113 CHAR szPath
[MAX_PATH
];
115 TRACE("(%p)->(path=%s flags=0x%08lx) \n",This
,debugstr_a(lpszPath
),dwFlags
);
117 if(!lpszPath
|| !lpszPath
[0]) return FALSE
;
119 strcpy(szPath
, lpszPath
);
120 PathAddBackslashA(szPath
);
121 strcat(szPath
,"*.*");
123 /*enumerate the folders*/
124 if(dwFlags
& SHCONTF_FOLDERS
)
126 TRACE("-- (%p)-> enumerate SHCONTF_FOLDERS of %s\n",This
,debugstr_a(szPath
));
127 hFile
= FindFirstFileA(szPath
,&stffile
);
128 if ( hFile
!= INVALID_HANDLE_VALUE
)
132 if ( !(dwFlags
& SHCONTF_INCLUDEHIDDEN
) && (stffile
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) ) continue;
133 if ( (stffile
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) && strcmp (stffile
.cFileName
, ".") && strcmp (stffile
.cFileName
, ".."))
135 pidl
= _ILCreateFolder (&stffile
);
136 if(pidl
&& AddToEnumList((IEnumIDList
*)This
, pidl
))
142 } while( FindNextFileA(hFile
,&stffile
));
147 /*enumerate the non-folder items (values) */
148 if(dwFlags
& SHCONTF_NONFOLDERS
)
150 TRACE("-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n",This
,debugstr_a(szPath
));
151 hFile
= FindFirstFileA(szPath
,&stffile
);
152 if ( hFile
!= INVALID_HANDLE_VALUE
)
156 if ( !(dwFlags
& SHCONTF_INCLUDEHIDDEN
) && (stffile
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) ) continue;
157 if (! (stffile
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) )
159 pidl
= _ILCreateValue(&stffile
);
160 if(pidl
&& AddToEnumList((IEnumIDList
*)This
, pidl
))
166 } while( FindNextFileA(hFile
,&stffile
));
173 BOOL
SHELL_RegisterCPanelApp(IEnumIDList
* list
, LPCSTR path
)
182 char displayName
[MAX_PATH
];
183 char comment
[MAX_PATH
];
185 WCHAR wpath
[MAX_PATH
];
187 MultiByteToWideChar(CP_ACP
, 0, path
, -1, wpath
, MAX_PATH
);
190 applet
= Control_LoadApplet(0, wpath
, &panel
);
193 for(i
=0; i
<applet
->count
; ++i
) {
194 WideCharToMultiByte(CP_ACP
, 0, applet
->info
[i
].szName
, -1, displayName
, MAX_PATH
, 0, 0);
195 WideCharToMultiByte(CP_ACP
, 0, applet
->info
[i
].szInfo
, -1, comment
, MAX_PATH
, 0, 0);
197 applet
->proc(0, CPL_INQUIRE
, i
, (LPARAM
)&info
);
200 iconIdx
= -info
.idIcon
; /* negative icon index instead of icon number */
204 pidl
= _ILCreateCPanel(path
, displayName
, comment
, iconIdx
);
207 AddToEnumList(list
, pidl
);
210 Control_UnloadApplet(applet
);
216 int SHELL_RegisterRegistryCPanelApps(IEnumIDList
* list
, HKEY hkey_root
, LPCSTR szRepPath
)
219 char value
[MAX_PATH
];
224 if (RegOpenKeyA(hkey_root
, szRepPath
, &hkey
) == ERROR_SUCCESS
)
229 DWORD nameLen
= MAX_PATH
;
230 DWORD valueLen
= MAX_PATH
;
232 if (RegEnumValueA(hkey
, idx
, name
, &nameLen
, NULL
, NULL
, (LPBYTE
)&value
, &valueLen
) != ERROR_SUCCESS
)
235 if (SHELL_RegisterCPanelApp(list
, value
))
245 int SHELL_RegisterCPanelFolders(IEnumIDList
* list
, HKEY hkey_root
, LPCSTR szRepPath
)
252 if (RegOpenKeyA(hkey_root
, szRepPath
, &hkey
) == ERROR_SUCCESS
)
257 if (RegEnumKeyA(hkey
, idx
, name
, MAX_PATH
) != ERROR_SUCCESS
)
261 LPITEMIDLIST pidl
= _ILCreateSpecial(name
);
263 if (pidl
&& AddToEnumList(list
, pidl
))
274 /**************************************************************************
275 * CreateCPanelEnumList()
277 static BOOL
CreateCPanelEnumList(
281 ICOM_THIS(IEnumIDListImpl
,iface
);
283 CHAR szPath
[MAX_PATH
];
284 WIN32_FIND_DATAA wfd
;
287 TRACE("(%p)->(flags=0x%08lx) \n",This
,dwFlags
);
289 /* enumerate control panel folders folders */
290 if (dwFlags
& SHCONTF_FOLDERS
)
291 SHELL_RegisterCPanelFolders((IEnumIDList
*)This
, HKEY_LOCAL_MACHINE
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
293 /* enumerate the control panel applets */
294 if (dwFlags
& SHCONTF_NONFOLDERS
)
298 GetSystemDirectoryA(szPath
, MAX_PATH
);
299 p
= PathAddBackslashA(szPath
);
302 TRACE("-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n",This
,debugstr_a(szPath
));
303 hFile
= FindFirstFileA(szPath
, &wfd
);
305 if (hFile
!= INVALID_HANDLE_VALUE
)
309 if (!(dwFlags
& SHCONTF_INCLUDEHIDDEN
) && (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
))
312 if (!(wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)) {
313 strcpy(p
, wfd
.cFileName
);
314 SHELL_RegisterCPanelApp((IEnumIDList
*)This
, szPath
);
316 } while(FindNextFileA(hFile
, &wfd
));
321 SHELL_RegisterRegistryCPanelApps((IEnumIDList
*)This
, HKEY_LOCAL_MACHINE
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
322 SHELL_RegisterRegistryCPanelApps((IEnumIDList
*)This
, HKEY_CURRENT_USER
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
328 /**************************************************************************
329 * CreateDesktopEnumList()
331 static BOOL
CreateDesktopEnumList(
335 ICOM_THIS(IEnumIDListImpl
,iface
);
337 LPITEMIDLIST pidl
=NULL
;
339 char szPath
[MAX_PATH
];
341 TRACE("(%p)->(flags=0x%08lx) \n",This
,dwFlags
);
343 /*enumerate the root folders */
344 if(dwFlags
& SHCONTF_FOLDERS
)
346 /*create the pidl for This item */
347 pidl
= _ILCreateMyComputer();
350 if(!AddToEnumList((IEnumIDList
*)This
, pidl
))
354 if (! RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\desktop\\NameSpace", 0, KEY_READ
, &hkey
))
361 DWORD size
= sizeof (iid
);
363 if (ERROR_SUCCESS
!=RegEnumKeyExA(hkey
, i
, iid
, &size
, 0, NULL
, NULL
, NULL
))
366 pidl
= _ILCreateSpecial(iid
);
369 AddToEnumList((IEnumIDList
*)This
, pidl
);
377 /*enumerate the elements in %windir%\desktop */
378 SHGetSpecialFolderPathA(0, szPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
379 CreateFolderEnumList( (IEnumIDList
*)This
, szPath
, dwFlags
);
384 /**************************************************************************
385 * CreateMyCompEnumList()
387 static BOOL
CreateMyCompEnumList(
391 ICOM_THIS(IEnumIDListImpl
,iface
);
393 LPITEMIDLIST pidl
=NULL
;
398 TRACE("(%p)->(flags=0x%08lx) \n",This
,dwFlags
);
400 /*enumerate the folders*/
401 if(dwFlags
& SHCONTF_FOLDERS
)
403 dwDrivemap
= GetLogicalDrives();
404 strcpy (szDriveName
,"A:\\");
405 while (szDriveName
[0]<='Z')
407 if(dwDrivemap
& 0x00000001L
)
409 pidl
= _ILCreateDrive(szDriveName
);
412 if(!AddToEnumList((IEnumIDList
*)This
, pidl
))
417 dwDrivemap
= dwDrivemap
>> 1;
420 TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n",This
);
421 if (! RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\mycomputer\\NameSpace", 0, KEY_READ
, &hkey
))
428 DWORD size
= sizeof (iid
);
430 if (ERROR_SUCCESS
!=RegEnumKeyExA(hkey
, i
, iid
, &size
, 0, NULL
, NULL
, NULL
))
433 pidl
= _ILCreateSpecial(iid
);
436 AddToEnumList((IEnumIDList
*)This
, pidl
);
446 /**************************************************************************
449 static BOOL
DeleteList(
452 ICOM_THIS(IEnumIDListImpl
,iface
);
456 TRACE("(%p)->()\n",This
);
459 { pDelete
= This
->mpFirst
;
460 This
->mpFirst
= pDelete
->pNext
;
461 SHFree(pDelete
->pidl
);
464 This
->mpFirst
= This
->mpLast
= This
->mpCurrent
= NULL
;
468 /**************************************************************************
469 * IEnumIDList_Folder_Constructor
473 IEnumIDList
* IEnumIDList_Constructor(
478 IEnumIDListImpl
* lpeidl
;
481 TRACE("()->(%s flags=0x%08lx kind=0x%08lx)\n",debugstr_a(lpszPath
),dwFlags
, dwKind
);
483 lpeidl
= (IEnumIDListImpl
*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IEnumIDListImpl
));
488 lpeidl
->lpVtbl
= &eidlvt
;
493 ret
= CreateDesktopEnumList((IEnumIDList
*)lpeidl
, dwFlags
);
497 ret
= CreateMyCompEnumList((IEnumIDList
*)lpeidl
, dwFlags
);
501 ret
= CreateFolderEnumList((IEnumIDList
*)lpeidl
, lpszPath
, dwFlags
);
505 ret
= CreateCPanelEnumList((IEnumIDList
*)lpeidl
, dwFlags
);
510 HeapFree(GetProcessHeap(),0,lpeidl
);
515 TRACE("-- (%p)->()\n",lpeidl
);
517 return (IEnumIDList
*)lpeidl
;
520 /**************************************************************************
521 * EnumIDList_QueryInterface
523 static HRESULT WINAPI
IEnumIDList_fnQueryInterface(
528 ICOM_THIS(IEnumIDListImpl
,iface
);
530 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
534 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
537 else if(IsEqualIID(riid
, &IID_IEnumIDList
)) /*IEnumIDList*/
538 { *ppvObj
= (IEnumIDList
*)This
;
542 { IEnumIDList_AddRef((IEnumIDList
*)*ppvObj
);
543 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
547 TRACE("-- Interface: E_NOINTERFACE\n");
548 return E_NOINTERFACE
;
551 /******************************************************************************
552 * IEnumIDList_fnAddRef
554 static ULONG WINAPI
IEnumIDList_fnAddRef(
557 ICOM_THIS(IEnumIDListImpl
,iface
);
558 TRACE("(%p)->(%lu)\n",This
,This
->ref
);
559 return ++(This
->ref
);
561 /******************************************************************************
562 * IEnumIDList_fnRelease
564 static ULONG WINAPI
IEnumIDList_fnRelease(
567 ICOM_THIS(IEnumIDListImpl
,iface
);
569 TRACE("(%p)->(%lu)\n",This
,This
->ref
);
571 if (!--(This
->ref
)) {
572 TRACE(" destroying IEnumIDList(%p)\n",This
);
573 DeleteList((IEnumIDList
*)This
);
574 HeapFree(GetProcessHeap(),0,This
);
580 /**************************************************************************
584 static HRESULT WINAPI
IEnumIDList_fnNext(
587 LPITEMIDLIST
* rgelt
,
590 ICOM_THIS(IEnumIDListImpl
,iface
);
596 TRACE("(%p)->(%ld,%p, %p)\n",This
,celt
,rgelt
,pceltFetched
);
598 /* It is valid to leave pceltFetched NULL when celt is 1. Some of explorer's
599 * subsystems actually use it (and so may a third party browser)
606 if(celt
> 1 && !pceltFetched
)
607 { return E_INVALIDARG
;
610 if(celt
> 0 && !This
->mpCurrent
)
614 for(i
= 0; i
< celt
; i
++)
615 { if(!(This
->mpCurrent
))
618 temp
= ILClone(This
->mpCurrent
->pidl
);
620 This
->mpCurrent
= This
->mpCurrent
->pNext
;
629 /**************************************************************************
632 static HRESULT WINAPI
IEnumIDList_fnSkip(
633 IEnumIDList
* iface
,ULONG celt
)
635 ICOM_THIS(IEnumIDListImpl
,iface
);
640 TRACE("(%p)->(%lu)\n",This
,celt
);
642 for(dwIndex
= 0; dwIndex
< celt
; dwIndex
++)
643 { if(!This
->mpCurrent
)
647 This
->mpCurrent
= This
->mpCurrent
->pNext
;
651 /**************************************************************************
652 * IEnumIDList_fnReset
654 static HRESULT WINAPI
IEnumIDList_fnReset(
657 ICOM_THIS(IEnumIDListImpl
,iface
);
659 TRACE("(%p)\n",This
);
660 This
->mpCurrent
= This
->mpFirst
;
663 /**************************************************************************
664 * IEnumIDList_fnClone
666 static HRESULT WINAPI
IEnumIDList_fnClone(
667 IEnumIDList
* iface
,LPENUMIDLIST
* ppenum
)
669 ICOM_THIS(IEnumIDListImpl
,iface
);
671 TRACE("(%p)->() to (%p)->() E_NOTIMPL\n",This
,ppenum
);
675 /**************************************************************************
676 * IEnumIDList_fnVTable
678 static ICOM_VTABLE (IEnumIDList
) eidlvt
=
680 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
681 IEnumIDList_fnQueryInterface
,
682 IEnumIDList_fnAddRef
,
683 IEnumIDList_fnRelease
,