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 = _ILCreateFromFindDataA (&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 = _ILCreateFromFindDataA(&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 = _ILCreateGuidFromStrA(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 = _ILCreateGuidFromStrA(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 = _ILCreateGuidFromStrA(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,