filelist.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 6k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //----------------------------------------------------------------------------
  2. //
  3. //----------------------------------------------------------------------------
  4. #include "shellprv.h"
  5. #pragma  hdrstop
  6. //----------------------------------------------------------------------------
  7. typedef LPITEMIDLIST PIDL;
  8. //----------------------------------------------------------------------------
  9. typedef struct
  10. {
  11.     // IShellLink *psl;    
  12.     // IPersistFile *ppf;
  13.     HDPA hdpaFLI;    
  14. } ENUM_INFO;
  15. typedef ENUM_INFO *PENUM_INFO;
  16. //----------------------------------------------------------------------------
  17. __inline UINT Sz_Cb(LPCTSTR psz)
  18. {
  19.     // NB We allocate an extra char in case we need to add an '&'.
  20.     return (lstrlen(psz)+2)*sizeof(TCHAR);
  21. }
  22. //----------------------------------------------------------------------------
  23. __inline static BOOL LAlloc(UINT cb, PVOID *ppv)
  24. {
  25.     *ppv = (PVOID*)LocalAlloc(LPTR, cb);
  26.     return *ppv ? TRUE : FALSE;
  27. }
  28. //----------------------------------------------------------------------------
  29. __inline static BOOL LFree(PVOID pv)
  30. {
  31.     return LocalFree(pv) ? FALSE : TRUE;
  32. }
  33. //----------------------------------------------------------------------------
  34. BOOL Sz_AllocCopy(LPCTSTR pszSrc, LPSTR *ppszDst)
  35. {
  36.     BOOL fRet = FALSE;
  37.     ASSERT(pszSrc && ppszDst);
  38.     
  39.     if (LAlloc(Sz_Cb(pszSrc), ppszDst))
  40.     {
  41.         lstrcpy(*ppszDst, pszSrc);
  42.         fRet = TRUE;
  43.     }
  44.     return fRet;
  45. }
  46. //----------------------------------------------------------------------------
  47. // Create a folder enum item.
  48. BOOL FileList_CreateItem(IShellFolder *psf, PIDL pidl, PFILELIST_ITEM *ppfli)
  49. {
  50.     ASSERT(psf && pidl && ppfli);
  51.     
  52.     if (LAlloc(sizeof(FILELIST_ITEM), ppfli))
  53.     {
  54.         STRRET str;
  55.         TCHAR szName[MAX_PATH];
  56.         
  57.         if (SUCCEEDED(psf->lpVtbl->GetDisplayNameOf(psf, pidl, SHGDN_NORMAL, &str)) &&
  58.             SUCCEEDED(StrRetToBuf(&str, pidl, szName, ARRAYSIZE(szName))))
  59.         {
  60.             PSTR pszName;
  61.             if (Sz_AllocCopy(szName, &pszName))
  62.             {
  63.                 DWORD dwAttribs = SFGAO_FOLDER | SFGAO_FILESYSTEM;
  64.                 if (SUCCEEDED(psf->lpVtbl->GetAttributesOf(psf, 1, &pidl, &dwAttribs)))
  65.                 {
  66.                     (*ppfli)->pszName = pszName;
  67.                     (*ppfli)->pidl = pidl;
  68.                     (*ppfli)->dwAttribs = dwAttribs;
  69.                     return TRUE;
  70.                 }
  71.                 ASSERT(FALSE);
  72.                 LFree(pszName);
  73.             }
  74.         }
  75.         ASSERT(FALSE);
  76.         LFree(*ppfli);
  77.         *ppfli = NULL;
  78.     }
  79.     return FALSE;
  80. }
  81. BOOL Folder_Enum(PIDL pidlFolder, PFN_FOLDER_ENUM_CALLBACK pfn, PVOID pv)
  82. {
  83.     BOOL fRet = FALSE;
  84.     IShellFolder *psfDesktop;
  85.     if (SUCCEEDED(SHGetDesktopFolder(&psfDesktop)))
  86.     {
  87.         IShellFolder *psf;
  88.         if (SUCCEEDED(psfDesktop->lpVtbl->BindToObject(psfDesktop, pidlFolder, NULL, &IID_IShellFolder, &psf)))
  89.         {
  90.             LPENUMIDLIST penum;
  91.             if (SUCCEEDED(psf->lpVtbl->EnumObjects(psf, NULL, SHCONTF_FOLDERS|SHCONTF_NONFOLDERS, &penum)))
  92.             {
  93.                 PIDL pidlItem;
  94.                 UINT celt;
  95.                 while (penum->lpVtbl->Next(penum, 1, &pidlItem, &celt)==NOERROR && celt==1)
  96.                 {
  97.                     // NB Callback function is responsible for nuking pidlItem if it
  98.                     // doesn't need it.
  99.                     if (!(*pfn)(psf, pidlFolder, pidlItem, pv))
  100.                         break;
  101.                 }
  102.                 fRet = TRUE;
  103.                 penum->lpVtbl->Release(penum);
  104.             }
  105.             psf->lpVtbl->Release(psf);
  106.         }
  107.         psfDesktop->lpVtbl->Release(psfDesktop);
  108.     }
  109.     return fRet;
  110. }
  111. //----------------------------------------------------------------------------
  112. BOOL FolderEnum_Callback(LPSHELLFOLDER psf, PIDL pidlFolder, PIDL pidlItem, LPVOID pv)
  113. {
  114.     PENUM_INFO pei = (PENUM_INFO)pv;
  115.     PFILELIST_ITEM pfli;
  116.     Assert (psf && pidlFolder && pidlItem && pei && pei->hdpaFLI);
  117.     if (FileList_CreateItem(psf, pidlItem, &pfli))
  118.         DPA_AppendPtr(pei->hdpaFLI, pfli);
  119.     
  120.     return TRUE;
  121. }
  122. //----------------------------------------------------------------------------
  123. BOOL FileList_Create(PIDL pidlFolder, HDPA *phdpa, PINT pcItems)
  124. {
  125.     BOOL fRet = FALSE;
  126.     ENUM_INFO ei;
  127.     
  128.     ASSERT(pidlFolder && phdpa);
  129.     if (pcItems)
  130.         *pcItems = 0;
  131.     *phdpa = DPA_Create(0);
  132.     if (*phdpa)
  133.     {
  134.         ei.hdpaFLI = *phdpa;
  135.         if (ei.hdpaFLI)
  136.         {
  137.             if (Folder_Enum(pidlFolder, FolderEnum_Callback, &ei))
  138.             {
  139.                 if (pcItems)
  140.                     *pcItems = DPA_GetPtrCount(*phdpa);
  141.                 fRet = TRUE;
  142.             }
  143.         }
  144.     }
  145.     
  146.     return fRet;
  147. }
  148. //---------------------------------------------------------------------------
  149. // Simplified version of the file info comparison function.
  150. int CALLBACK FileList_ItemCompare(PFILELIST_ITEM pfli1, PFILELIST_ITEM pfli2, LPARAM lParam)
  151. {
  152.     // Directories come first, then files and links.
  153.     if ((pfli1->dwAttribs & SFGAO_FOLDER) > (pfli2->dwAttribs & SFGAO_FOLDER))
  154.         return -1;
  155.     else if ((pfli1->dwAttribs & SFGAO_FOLDER) < (pfli2->dwAttribs & SFGAO_FOLDER))
  156.         return 1;
  157.     return lstrcmpi(pfli1->pszName, pfli2->pszName);
  158. }
  159. //---------------------------------------------------------------------------
  160. // Sort the list alphabetically.
  161. BOOL FileList_Sort(HDPA hdpaFLI)
  162. {
  163.     return DPA_Sort(hdpaFLI, FileList_ItemCompare, 0);
  164. }
  165. //---------------------------------------------------------------------------
  166. void FileList_DestroyItem(PFILELIST_ITEM pfli)
  167. {
  168.     // NB The pidl's are used by the menu itself, it will clean them up as 
  169.     // needed so we don't have to do it here.
  170.     if (pfli->pszName)
  171.         LFree(pfli->pszName);
  172. }
  173. //---------------------------------------------------------------------------
  174. void FileList_Destroy(HDPA hdpa)
  175. {
  176.     int cItems = DPA_GetPtrCount(hdpa);
  177.     int i;
  178.     for (i=0; i<cItems; i++)
  179.     {
  180.         PFILELIST_ITEM pfli = DPA_GetPtr(hdpa, i);
  181.         FileList_DestroyItem(pfli);
  182.     }
  183.     DPA_Destroy(hdpa);
  184. }