home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2006 April / DPPRO0406DVD.ISO / Essentials / Programming / Notepad2 / Source / NP2SRC.ZIP / Dlapi.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-06-25  |  43.3 KB  |  1,738 lines

  1. /******************************************************************************
  2. *
  3. *
  4. * Notepad2
  5. *
  6. * Dlapi.c
  7. *   Directory Listing APIs used in Notepad2
  8. *
  9. * See Readme.txt for more information about this source code.
  10. * Please send me your comments to this work.
  11. *
  12. * Distributed under the terms of the GNU General Public License,
  13. * see License.txt for details.
  14. *
  15. *                                              (c) Florian Balmer 1996-2004
  16. *                                                       textview@bluewin.ch
  17. *                                               http://www.flos-freeware.ch
  18. *
  19. *
  20. ******************************************************************************/
  21. #include <windows.h>
  22. #include <commctrl.h>
  23. #include <shlobj.h>
  24. #include <shlwapi.h>
  25. #include <string.h>
  26. #include "dlapi.h"
  27.  
  28.  
  29.  
  30. //==== Global LPMALLOC instance ===============================================
  31. extern LPMALLOC g_lpMalloc;
  32.  
  33.  
  34.  
  35. //==== DirList ================================================================
  36.  
  37. //==== DLDATA Structure =======================================================
  38.  
  39. typedef struct tagDLDATA // dl
  40. {
  41.  
  42.   HWND hwnd;                 // HWND of ListView Control
  43.   UINT cbidl;                // Size of pidl
  44.   LPITEMIDLIST  pidl;        // Directory Id
  45.   LPSHELLFOLDER lpsf;        // IShellFolder Interface to pidl
  46.   char szPath[MAX_PATH];     // Pathname to Directory Id
  47.   int iDefIconFolder;        // Default Folder Icon
  48.   int iDefIconFile;          // Default File Icon
  49.   BOOL bNoFadeHidden;        // Flag passed from GetDispInfo()
  50.   HANDLE hExitThread;        // Flag is set when Icon Thread should terminate
  51.   HANDLE hTerminatedThread;  // Flag is set when Icon Thread has terminated
  52.  
  53. } DLDATA, *LPDLDATA;
  54.  
  55.  
  56. //==== Property Name ==========================================================
  57. static const char *pDirListProp = "DirListData";
  58.  
  59.  
  60.  
  61. //=============================================================================
  62. //
  63. //  DirList_Init()
  64. //
  65. //  Initializes the DLDATA structure and sets up the listview control
  66. //
  67. BOOL DirList_Init(HWND hwnd,LPCSTR pszHeader)
  68. {
  69.  
  70.   HIMAGELIST hil;
  71.   SHFILEINFO shfi;
  72.   LV_COLUMN  lvc;
  73.  
  74.   // Allocate DirListData Property
  75.   LPDLDATA lpdl = (LPVOID)GlobalAlloc(GPTR,sizeof(DLDATA));
  76.   SetProp(hwnd,pDirListProp,(HANDLE)lpdl);
  77.  
  78.   // Setup dl
  79.   lpdl->hwnd = hwnd;
  80.   lpdl->cbidl = 0;
  81.   lpdl->pidl = NULL;
  82.   lpdl->lpsf = NULL;
  83.   lstrcpy(lpdl->szPath,"");
  84.  
  85.   // Add Imagelists
  86.   hil = (HIMAGELIST)SHGetFileInfo("C:\\",0,&shfi,sizeof(SHFILEINFO),
  87.                     SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  88.  
  89.   ListView_SetImageList(hwnd,hil,LVSIL_SMALL);
  90.  
  91.   hil = (HIMAGELIST)SHGetFileInfo("C:\\",0,&shfi,sizeof(SHFILEINFO),
  92.                     SHGFI_LARGEICON | SHGFI_SYSICONINDEX);
  93.  
  94.   ListView_SetImageList(hwnd,hil,LVSIL_NORMAL);
  95.  
  96.   // Initialize default icons - done in DirList_Fill()
  97.   //SHGetFileInfo("Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
  98.   //  SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  99.   //lpdl->iDefIconFolder = shfi.iIcon;
  100.  
  101.   //SHGetFileInfo("Icon",FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
  102.   //  SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  103.   //lpdl->iDefIconFile = shfi.iIcon;
  104.  
  105.   lpdl->iDefIconFolder = 0;
  106.   lpdl->iDefIconFile = 0;
  107.  
  108.   // Icon thread control
  109.   lpdl->hExitThread = CreateEvent(NULL,TRUE,FALSE,NULL);
  110.   lpdl->hTerminatedThread = CreateEvent(NULL,TRUE,TRUE,NULL);
  111.  
  112.   lvc;
  113.   pszHeader;
  114.  
  115.   return TRUE;
  116.  
  117. }
  118.  
  119.  
  120. //=============================================================================
  121. //
  122. //  DirList_Destroy()
  123. //
  124. //  Free memory used by dl structure
  125. //
  126. BOOL DirList_Destroy(HWND hwnd)
  127. {
  128.  
  129.   //LPMALLOC lpMalloc;
  130.  
  131.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  132.  
  133.   // Release multithreading objects
  134.   DirList_TerminateIconThread(hwnd);
  135.   CloseHandle(lpdl->hExitThread);
  136.   CloseHandle(lpdl->hTerminatedThread);
  137.  
  138.   //if (NOERROR == SHGetMalloc(&lpMalloc))
  139.   //{
  140.  
  141.     if (lpdl->pidl)
  142.       g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdl->pidl);
  143.  
  144.     //lpMalloc->lpVtbl->Release(lpMalloc);
  145.  
  146.     if (lpdl->lpsf)
  147.       lpdl->lpsf->lpVtbl->Release(lpdl->lpsf);
  148.  
  149.   //}
  150.  
  151.   // Free DirListData Property
  152.   RemoveProp(hwnd,pDirListProp);
  153.   GlobalFree(lpdl);
  154.  
  155.   return FALSE;
  156.  
  157. }
  158.  
  159.  
  160. //=============================================================================
  161. //
  162. //  DirList_StartIconThread()
  163. //
  164. //  Start thread to extract file icons in the background
  165. //
  166. BOOL DirList_StartIconThread(HWND hwnd)
  167. {
  168.  
  169.   DWORD dwtid;
  170.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  171.  
  172.   DirList_TerminateIconThread(hwnd);
  173.  
  174.   ResetEvent(lpdl->hExitThread);
  175.   //ResetEvent(lpdl->hTerminatedThread);
  176.  
  177.   CreateThread(NULL,0,DirList_IconThread,(LPVOID)lpdl,0,&dwtid);
  178.  
  179.   return TRUE;
  180.  
  181. }
  182.  
  183.  
  184. //=============================================================================
  185. //
  186. //  DirList_TerminateIconThread()
  187. //
  188. //  Terminate Icon Thread and reset multithreading control structures
  189. //
  190. BOOL DirList_TerminateIconThread(HWND hwnd)
  191. {
  192.  
  193.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  194.  
  195.   SetEvent(lpdl->hExitThread);
  196.  
  197.   //WaitForSingleObject(lpdl->hTerminatedThread,INFINITE);
  198.   while (WaitForSingleObject(lpdl->hTerminatedThread,0) != WAIT_OBJECT_0)
  199.   {
  200.     MSG msg;
  201.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
  202.       TranslateMessage(&msg);
  203.       DispatchMessage(&msg);
  204.     }
  205.   }
  206.  
  207.   ResetEvent(lpdl->hExitThread);
  208.   SetEvent(lpdl->hTerminatedThread);
  209.  
  210.   return TRUE;
  211.  
  212. }
  213.  
  214.  
  215. //=============================================================================
  216. //
  217. //  DirList_Fill()
  218. //
  219. //  Snapshots a directory and displays the items in the listview control
  220. //
  221. int DirList_Fill(HWND hwnd,LPCSTR lpszDir,DWORD grfFlags,LPCSTR lpszFileSpec,
  222.                  BOOL bExcludeFilter,BOOL bNoFadeHidden)
  223. {
  224.  
  225.   WCHAR wszDir[MAX_PATH];
  226.  
  227.   //LPMALLOC lpMalloc = NULL;
  228.  
  229.   LPSHELLFOLDER lpsfDesktop = NULL;
  230.   LPSHELLFOLDER lpsf = NULL;
  231.  
  232.   LPITEMIDLIST  pidl = NULL;
  233.   LPITEMIDLIST  pidlEntry = NULL;
  234.  
  235.   LPENUMIDLIST  lpe = NULL;
  236.  
  237.   LV_ITEM       lvi;
  238.   LPLV_ITEMDATA lplvid;
  239.  
  240.   ULONG chParsed = 0;
  241.   ULONG dwAttributes = 0;
  242.  
  243.   DL_FILTER dlf;
  244.   SHFILEINFO shfi;
  245.  
  246.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  247.  
  248.   // Initialize default icons
  249.   SHGetFileInfo("Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
  250.     SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  251.   lpdl->iDefIconFolder = shfi.iIcon;
  252.  
  253.   SHGetFileInfo("Icon",FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
  254.     SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  255.   lpdl->iDefIconFile = shfi.iIcon;
  256.  
  257.   // First of all terminate running icon thread
  258.   DirList_TerminateIconThread(hwnd);
  259.  
  260.   // A Directory is strongly required
  261.   if (!lpszDir || !*lpszDir)
  262.     return(-1);
  263.  
  264.   lstrcpy(lpdl->szPath,lpszDir);
  265.  
  266.   // Init ListView
  267.   SendMessage(hwnd,WM_SETREDRAW,0,0);
  268.   ListView_DeleteAllItems(hwnd);
  269.  
  270.   // Init Filter
  271.   DirList_CreateFilter(&dlf,lpszFileSpec,bExcludeFilter);
  272.  
  273.   // Init lvi
  274.   lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  275.   lvi.iItem = 0;
  276.   lvi.iSubItem = 0;
  277.   lvi.pszText = LPSTR_TEXTCALLBACK;
  278.   lvi.cchTextMax = MAX_PATH;
  279.   lvi.iImage = I_IMAGECALLBACK;
  280.  
  281.   // Convert Directory to a UNICODE string
  282.   MultiByteToWideChar(CP_ACP,
  283.                       MB_PRECOMPOSED,
  284.                       lpszDir,
  285.                       -1,
  286.                       wszDir,
  287.                       MAX_PATH);
  288.  
  289.  
  290.   // Get Shell's IMalloc Interface
  291.   //if (NOERROR == SHGetMalloc(&lpMalloc))
  292.   //{
  293.  
  294.     // Get Desktop Folder
  295.     if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
  296.     {
  297.  
  298.       // Convert wszDir into a pidl
  299.       if (NOERROR == lpsfDesktop->lpVtbl->ParseDisplayName(
  300.                                             lpsfDesktop,
  301.                                             hwnd,
  302.                                             NULL,
  303.                                             wszDir,
  304.                                             &chParsed,
  305.                                             &pidl,
  306.                                             &dwAttributes))
  307.  
  308.       {
  309.  
  310.         // Bind pidl to IShellFolder
  311.         if (NOERROR == lpsfDesktop->lpVtbl->BindToObject(
  312.                                               lpsfDesktop,
  313.                                               pidl,
  314.                                               NULL,
  315.                                               &IID_IShellFolder,
  316.                                               &lpsf))
  317.  
  318.         {
  319.  
  320.           // Create an Enumeration object for lpsf
  321.           if (NOERROR == lpsf->lpVtbl->EnumObjects(
  322.                                          lpsf,
  323.                                          hwnd,
  324.                                          grfFlags,
  325.                                          &lpe))
  326.  
  327.           {
  328.  
  329.             // Enumerate the contents of lpsf
  330.             while (NOERROR == lpe->lpVtbl->Next(
  331.                                              lpe,
  332.                                              1,
  333.                                              &pidlEntry,
  334.                                              NULL))
  335.  
  336.             {
  337.  
  338.               // Add found item to the List
  339.               // Check if it's part of the Filesystem
  340.               dwAttributes = SFGAO_FILESYSTEM | SFGAO_FOLDER;
  341.  
  342.               lpsf->lpVtbl->GetAttributesOf(
  343.                               lpsf,
  344.                               1,
  345.                               &pidlEntry,
  346.                               &dwAttributes);
  347.  
  348.               if (dwAttributes & SFGAO_FILESYSTEM)
  349.               {
  350.  
  351.                 // Check if item matches specified filter
  352.                 if (DirList_MatchFilter(lpsf,pidlEntry,&dlf))
  353.                 {
  354.  
  355.                   lplvid = g_lpMalloc->lpVtbl->Alloc(
  356.                                                 g_lpMalloc,
  357.                                                 sizeof(LV_ITEMDATA));
  358.  
  359.                   lplvid->pidl = pidlEntry;
  360.                   lplvid->lpsf = lpsf;
  361.  
  362.                   lpsf->lpVtbl->AddRef(lpsf);
  363.  
  364.                   lvi.lParam = (LPARAM)lplvid;
  365.  
  366.                   // Setup default Icon - Folder or File
  367.                   lvi.iImage = (dwAttributes & SFGAO_FOLDER) ?
  368.                     lpdl->iDefIconFolder : lpdl->iDefIconFile;
  369.  
  370.                   ListView_InsertItem(hwnd,&lvi);
  371.  
  372.                   lvi.iItem++;
  373.  
  374.                 }
  375.  
  376.               }
  377.  
  378.               //lpMalloc->lpVtbl->Free(lpMalloc,pidlEntry);
  379.  
  380.             } // IEnumIDList::Next()
  381.  
  382.             lpe->lpVtbl->Release(lpe);
  383.  
  384.           } // IShellFolder::EnumObjects()
  385.  
  386.         } // IShellFolder::BindToObject()
  387.  
  388.       } // IShellFolder::ParseDisplayName()
  389.  
  390.       lpsfDesktop->lpVtbl->Release(lpsfDesktop);
  391.  
  392.     } // SHGetDesktopFolder()
  393.  
  394.     if (lpdl->pidl)
  395.       g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdl->pidl);
  396.  
  397.     if (lpdl->lpsf && lpdl->lpsf->lpVtbl)
  398.       lpdl->lpsf->lpVtbl->Release(lpdl->lpsf);
  399.  
  400.     //lpMalloc->lpVtbl->Release(lpMalloc);
  401.  
  402.   //} // SHGetMalloc()
  403.  
  404.   // Set lpdl
  405.   lpdl->cbidl = IL_GetSize(pidl);
  406.   lpdl->pidl = pidl;
  407.   lpdl->lpsf = lpsf;
  408.   lpdl->bNoFadeHidden = bNoFadeHidden;
  409.  
  410.   // Set column width to fit window
  411.   //ListView_SetColumnWidth(hwnd,0,LVSCW_AUTOSIZE);
  412.  
  413.   // Redraw Listview
  414.   SendMessage(hwnd,WM_SETREDRAW,1,0);
  415.  
  416.   // Return number of items in the control
  417.   return (ListView_GetItemCount(hwnd));
  418.  
  419. }
  420.  
  421.  
  422. //=============================================================================
  423. //
  424. //  DirList_IconThread()
  425. //
  426. //  Thread to extract file icons in the background
  427. //
  428. DWORD WINAPI DirList_IconThread(LPVOID lpParam)
  429. {
  430.  
  431.   HWND hwnd;
  432.  
  433.   LPDLDATA lpdl;
  434.   LV_ITEM lvi;
  435.   LPLV_ITEMDATA lplvid;
  436.  
  437.   LPMALLOC lpMalloc;
  438.   LPSHELLICON lpshi;
  439.  
  440.   int iItem = 0;
  441.   int iMaxItem;
  442.  
  443.   lpdl = (LPDLDATA)lpParam;
  444.   ResetEvent(lpdl->hTerminatedThread);
  445.  
  446.   // Exit immediately if DirList_Fill() hasn't been called
  447.   if (!lpdl->lpsf) {
  448.     SetEvent(lpdl->hTerminatedThread);
  449.     ExitThread(0);
  450.     return(0);
  451.   }
  452.  
  453.   hwnd = lpdl->hwnd;
  454.   iMaxItem = ListView_GetItemCount(hwnd);
  455.  
  456.   CoInitialize(NULL);
  457.   SHGetMalloc(&lpMalloc);
  458.  
  459.   // Get IShellIcon
  460.   lpdl->lpsf->lpVtbl->QueryInterface(lpdl->lpsf,&IID_IShellIcon,&lpshi);
  461.  
  462.   while (iItem < iMaxItem && WaitForSingleObject(lpdl->hExitThread,0) != WAIT_OBJECT_0) {
  463.  
  464.     lvi.iItem = iItem;
  465.     lvi.mask  = LVIF_PARAM;
  466.     if (ListView_GetItem(hwnd,&lvi)) {
  467.  
  468.       SHFILEINFO shfi;
  469.       LPITEMIDLIST pidl;
  470.       DWORD dwAttributes = SFGAO_LINK | SFGAO_SHARE;
  471.  
  472.       lplvid = (LPLV_ITEMDATA)lvi.lParam;
  473.  
  474.       lvi.mask = LVIF_IMAGE;
  475.  
  476.       if (!lpshi || NOERROR != lpshi->lpVtbl->GetIconOf(lpshi,lplvid->pidl,GIL_FORSHELL,&lvi.iImage))
  477.       {
  478.         pidl = IL_Create(lpMalloc,lpdl->pidl,lpdl->cbidl,lplvid->pidl,0);
  479.         SHGetFileInfo((LPCSTR)pidl,0,&shfi,sizeof(SHFILEINFO),SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  480.         lpMalloc->lpVtbl->Free(lpMalloc,pidl);
  481.         lvi.iImage = shfi.iIcon;
  482.       }
  483.  
  484.       // It proved necessary to reset the state bits...
  485.       lvi.stateMask = 0;
  486.       lvi.state = 0;
  487.  
  488.       // Link and Share Overlay
  489.       lplvid->lpsf->lpVtbl->GetAttributesOf(
  490.                               lplvid->lpsf,
  491.                               1,&lplvid->pidl,
  492.                               &dwAttributes);
  493.  
  494.       if (dwAttributes & SFGAO_LINK)
  495.       {
  496.         lvi.mask |= LVIF_STATE;
  497.         lvi.stateMask |= LVIS_OVERLAYMASK;
  498.         lvi.state |= INDEXTOOVERLAYMASK(2);
  499.       }
  500.  
  501.       if (dwAttributes & SFGAO_SHARE)
  502.       {
  503.         lvi.mask |= LVIF_STATE;
  504.         lvi.stateMask |= LVIS_OVERLAYMASK;
  505.         lvi.state |= INDEXTOOVERLAYMASK(1);
  506.       }
  507.  
  508.       // Fade hidden/system files
  509.       if (!lpdl->bNoFadeHidden)
  510.       {
  511.         WIN32_FIND_DATA fd;
  512.         if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,lplvid->pidl,
  513.                         SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA)))
  514.         {
  515.           if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
  516.               (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
  517.           {
  518.             lvi.mask |= LVIF_STATE;
  519.             lvi.stateMask |= LVIS_CUT;
  520.             lvi.state |= LVIS_CUT;
  521.           }
  522.         }
  523.       }
  524.       //MessageBox(NULL,NULL,NULL,MB_ICONWARNING);
  525.       lvi.iSubItem = 0;
  526.       ListView_SetItem(hwnd,&lvi);
  527.     }
  528.     iItem++;
  529.   }
  530.  
  531.   if (lpshi)
  532.     lpshi->lpVtbl->Release(lpshi);
  533.  
  534.   lpMalloc->lpVtbl->Release(lpMalloc);
  535.   CoUninitialize();
  536.  
  537.   SetEvent(lpdl->hTerminatedThread);
  538.   ExitThread(0);
  539.   return(0);
  540.  
  541. }
  542.  
  543.  
  544. //=============================================================================
  545. //
  546. //  DirList_GetDispInfo()
  547. //
  548. //  Must be called in response to a WM_NOTIFY/LVN_GETDISPINFO message from
  549. //  the listview control
  550. //
  551. BOOL DirList_GetDispInfo(HWND hwnd,LPARAM lParam,BOOL bNoFadeHidden)
  552. {
  553.  
  554.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  555.  
  556.   LV_DISPINFO *lpdi = (LPVOID)lParam;
  557.  
  558.   LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lpdi->item.lParam;
  559.  
  560.   // SubItem 0 is handled only
  561.   if (lpdi->item.iSubItem != 0)
  562.     return FALSE;
  563.  
  564.   // Text
  565.   if (lpdi->item.mask & LVIF_TEXT)
  566.     IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_INFOLDER,
  567.                       lpdi->item.pszText,lpdi->item.cchTextMax);
  568.  
  569.   // Image
  570.   //if (lpdi->item.mask & LVIF_IMAGE)
  571.   //{
  572.  
  573.   //  //LPMALLOC lpMalloc;
  574.   //  SHFILEINFO shfi;
  575.   //  LPITEMIDLIST pidl;
  576.   //  DWORD dwAttributes = SFGAO_LINK | SFGAO_SHARE;
  577.  
  578.   //  //if (NOERROR == SHGetMalloc(&lpMalloc))
  579.   //  //{
  580.  
  581.   //    // Generate Full Qualified pidl
  582.   //    pidl = IL_Create(g_lpMalloc,lpdl->pidl,lpdl->cbidl,lplvid->pidl,0);
  583.  
  584.   //    SHGetFileInfo((LPCSTR)pidl,0,&shfi,sizeof(SHFILEINFO),SHGFI_PIDL | SHGFI_SYSICONINDEX);
  585.  
  586.   //    lpdi->item.iImage = shfi.iIcon;
  587.  
  588.   //    g_lpMalloc->lpVtbl->Free(g_lpMalloc,pidl);
  589.   //    //lpMalloc->lpVtbl->Release(lpMalloc);
  590.  
  591.   //  //}
  592.  
  593.   //  // It proved necessary to reset the state bits...
  594.   //  lpdi->item.stateMask = 0;
  595.   //  lpdi->item.state = 0;
  596.  
  597.   //  // Link and Share Overlay
  598.   //  lplvid->lpsf->lpVtbl->GetAttributesOf(
  599.   //                          lplvid->lpsf,
  600.   //                          1,&lplvid->pidl,
  601.   //                          &dwAttributes);
  602.  
  603.   //  if (dwAttributes & SFGAO_LINK)
  604.   //  {
  605.   //    lpdi->item.mask |= LVIF_STATE;
  606.   //    lpdi->item.stateMask |= LVIS_OVERLAYMASK;
  607.   //    lpdi->item.state |= INDEXTOOVERLAYMASK(2);
  608.   //  }
  609.  
  610.   //  if (dwAttributes & SFGAO_SHARE)
  611.   //  {
  612.   //    lpdi->item.mask |= LVIF_STATE;
  613.   //    lpdi->item.stateMask |= LVIS_OVERLAYMASK;
  614.   //    lpdi->item.state |= INDEXTOOVERLAYMASK(1);
  615.   //  }
  616.  
  617.   //  // Fade hidden/system files
  618.   //  if (!bNoFadeHidden)
  619.   //  {
  620.   //    WIN32_FIND_DATA fd;
  621.   //    if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,lplvid->pidl,
  622.   //                     SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA)))
  623.   //    {
  624.   //      if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
  625.   //          (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
  626.   //      {
  627.   //        lpdi->item.mask |= LVIF_STATE;
  628.   //        lpdi->item.stateMask |= LVIS_CUT;
  629.   //        lpdi->item.state |= LVIS_CUT;
  630.   //      }
  631.   //    }
  632.  
  633.   //  }
  634.  
  635.   //}
  636.  
  637.   // Set values
  638.   lpdi->item.mask |= LVIF_DI_SETITEM;
  639.  
  640.   return TRUE;
  641.  
  642. }
  643.  
  644.  
  645. //=============================================================================
  646. //
  647. //  DirList_DeleteItem()
  648. //
  649. //  Must be called in response to a WM_NOTIFY/LVN_DELETEITEM message
  650. //  from the control
  651. //
  652. BOOL DirList_DeleteItem(HWND hwnd,LPARAM lParam)
  653. {
  654.  
  655.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  656.  
  657.   LV_ITEM lvi;
  658.   //LPMALLOC lpMalloc;
  659.  
  660.   NM_LISTVIEW *lpnmlv = (LPVOID)lParam;
  661.  
  662.   lvi.iItem = lpnmlv->iItem;
  663.   lvi.iSubItem = 0;
  664.   lvi.mask = LVIF_PARAM;
  665.  
  666.   if (ListView_GetItem(hwnd,&lvi))
  667.   {
  668.  
  669.     //if (NOERROR == SHGetMalloc(&lpMalloc))
  670.     //{
  671.  
  672.       // Free mem
  673.       LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lvi.lParam;
  674.       g_lpMalloc->lpVtbl->Free(g_lpMalloc,lplvid->pidl);
  675.       lplvid->lpsf->lpVtbl->Release(lplvid->lpsf);
  676.  
  677.       g_lpMalloc->lpVtbl->Free(g_lpMalloc,lplvid);
  678.  
  679.       //lpMalloc->lpVtbl->Release(lpMalloc);
  680.  
  681.       return TRUE;
  682.  
  683.     //}
  684.  
  685.   }
  686.  
  687.   else
  688.     return FALSE;
  689.  
  690. }
  691.  
  692.  
  693. //=============================================================================
  694. //
  695. //  DirList_CompareProc()
  696. //
  697. //  Compares two list items
  698. //
  699. int CALLBACK DirList_CompareProcFw(LPARAM lp1,LPARAM lp2,LPARAM lFlags)
  700. {
  701.  
  702.   HRESULT hr;
  703.  
  704.   LPLV_ITEMDATA lplvid1 = (LPLV_ITEMDATA)lp1;
  705.   LPLV_ITEMDATA lplvid2 = (LPLV_ITEMDATA)lp2;
  706.  
  707.   hr = (lplvid1->lpsf->lpVtbl->CompareIDs(
  708.                                  lplvid1->lpsf,
  709.                                  lFlags,
  710.                                  lplvid1->pidl,
  711.                                  lplvid2->pidl));
  712.  
  713.   return(short)(SCODE_CODE(GetScode(hr)));
  714.  
  715. }
  716.  
  717. int CALLBACK DirList_CompareProcRw(LPARAM lp1,LPARAM lp2,LPARAM lFlags)
  718. {
  719.  
  720.   HRESULT hr;
  721.  
  722.   LPLV_ITEMDATA lplvid1 = (LPLV_ITEMDATA)lp1;
  723.   LPLV_ITEMDATA lplvid2 = (LPLV_ITEMDATA)lp2;
  724.  
  725.   hr = (lplvid1->lpsf->lpVtbl->CompareIDs(
  726.                                  lplvid1->lpsf,
  727.                                  lFlags,
  728.                                  lplvid1->pidl,
  729.                                  lplvid2->pidl));
  730.  
  731.   return(-(short)(SCODE_CODE(GetScode(hr))));
  732.  
  733. }
  734.  
  735.  
  736. //=============================================================================
  737. //
  738. //  DirList_Sort()
  739. //
  740. //  Sorts the listview control by the specified order
  741. //
  742. BOOL DirList_Sort(HWND hwnd,int lFlags,BOOL fRev)
  743. {
  744.  
  745.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  746.  
  747.   if (fRev)
  748.  
  749.     return ListView_SortItems(hwnd,DirList_CompareProcRw,lFlags);
  750.  
  751.   else
  752.  
  753.     return ListView_SortItems(hwnd,DirList_CompareProcFw,lFlags);
  754.  
  755. }
  756.  
  757.  
  758. //=============================================================================
  759. //
  760. //  DirList_GetItem()
  761. //
  762. //  Copies the data of the specified item in the listview control to a buffer
  763. //
  764. int DirList_GetItem(HWND hwnd,int iItem,LPDLITEM lpdli)
  765. {
  766.  
  767.   LV_ITEM lvi;
  768.   LPLV_ITEMDATA lplvid;
  769.  
  770.   ULONG dwAttributes = SFGAO_FILESYSTEM;
  771.  
  772.  
  773.   if (iItem == -1)
  774.   {
  775.  
  776.     if (ListView_GetSelectedCount(hwnd))
  777.  
  778.       iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
  779.  
  780.     else
  781.  
  782.       return(-1);
  783.  
  784.   }
  785.  
  786.   lvi.mask = LVIF_PARAM;
  787.   lvi.iItem = iItem;
  788.   lvi.iSubItem = 0;
  789.  
  790.   if (!ListView_GetItem(hwnd,&lvi))
  791.   {
  792.  
  793.     if (lpdli->mask & DLI_TYPE)
  794.  
  795.       lpdli->ntype = DLE_NONE;
  796.  
  797.     return(-1);
  798.  
  799.   }
  800.  
  801.   lplvid = (LPLV_ITEMDATA)lvi.lParam;
  802.  
  803.   // Filename
  804.   if (lpdli->mask & DLI_FILENAME)
  805.  
  806.     IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_FORPARSING,
  807.                       lpdli->szFileName,MAX_PATH);
  808.  
  809.   // Displayname
  810.   if (lpdli->mask & DLI_DISPNAME)
  811.  
  812.     IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_INFOLDER,
  813.                       lpdli->szDisplayName,MAX_PATH);
  814.  
  815.   // Type (File / Directory)
  816.   if (lpdli->mask & DLI_TYPE)
  817.   {
  818.  
  819.     WIN32_FIND_DATA fd;
  820.  
  821.     if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,
  822.                                        lplvid->pidl,
  823.                                        SHGDFIL_FINDDATA,
  824.                                        &fd,
  825.                                        sizeof(WIN32_FIND_DATA)))
  826.  
  827.     lpdli->ntype = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
  828.                     DLE_DIR : DLE_FILE;
  829.  
  830.     /*lplvid->lpsf->lpVtbl->GetAttributesOf(
  831.                             lplvid->lpsf,
  832.                             1,
  833.                             &lplvid->pidl,
  834.                             &dwAttributes);
  835.  
  836.     lpdli->ntype = (dwAttributes & SFGAO_FOLDER) ? DLE_DIR : DLE_FILE;*/
  837.  
  838.   }
  839.  
  840.   return iItem;
  841.  
  842. }
  843.  
  844.  
  845. //=============================================================================
  846. //
  847. //  DirList_GetItemEx()
  848. //
  849. //  Retrieves extended infomration on a dirlist item
  850. //
  851. int DirList_GetItemEx(HWND hwnd,int iItem,LPWIN32_FIND_DATA pfd)
  852. {
  853.  
  854.   LV_ITEM lvi;
  855.   LPLV_ITEMDATA lplvid;
  856.  
  857.  
  858.   if (iItem == -1)
  859.   {
  860.  
  861.     if (ListView_GetSelectedCount(hwnd))
  862.  
  863.       iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
  864.  
  865.     else
  866.  
  867.       return(-1);
  868.  
  869.   }
  870.  
  871.   lvi.mask = LVIF_PARAM;
  872.   lvi.iItem = iItem;
  873.   lvi.iSubItem = 0;
  874.  
  875.   if (!ListView_GetItem(hwnd,&lvi))
  876.     return(-1);
  877.  
  878.   lplvid = (LPLV_ITEMDATA)lvi.lParam;
  879.  
  880.   if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,
  881.                                      lplvid->pidl,
  882.                                      SHGDFIL_FINDDATA,
  883.                                      pfd,
  884.                                      sizeof(WIN32_FIND_DATA)))
  885.     return iItem;
  886.  
  887.   else
  888.     return(-1);
  889.  
  890. }
  891.  
  892.  
  893. //=============================================================================
  894. //
  895. //  DirList_PropertyDlg()
  896. //
  897. //  Shows standard Win95 Property Dlg for selected Item
  898. //
  899. BOOL DirList_PropertyDlg(HWND hwnd,int iItem)
  900. {
  901.  
  902.   LV_ITEM lvi;
  903.   LPLV_ITEMDATA lplvid;
  904.   LPCONTEXTMENU lpcm;
  905.   CMINVOKECOMMANDINFO cmi;
  906.   BOOL bSuccess = TRUE;
  907.  
  908.   static const char *lpVerb = "properties";
  909.  
  910.   if (iItem == -1)
  911.   {
  912.     if (ListView_GetSelectedCount(hwnd))
  913.       iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
  914.  
  915.     else
  916.       return FALSE;
  917.   }
  918.  
  919.   lvi.mask = LVIF_PARAM;
  920.   lvi.iItem = iItem;
  921.   lvi.iSubItem = 0;
  922.  
  923.   if (!ListView_GetItem(hwnd,&lvi))
  924.     return FALSE;
  925.  
  926.   lplvid = (LPLV_ITEMDATA)lvi.lParam;
  927.  
  928.   if (NOERROR == lplvid->lpsf->lpVtbl->GetUIObjectOf(
  929.                                          lplvid->lpsf,
  930.                                          GetParent(hwnd),  // Owner
  931.                                          1,                // Number of objects
  932.                                          &lplvid->pidl,    // pidl
  933.                                          &IID_IContextMenu,
  934.                                          NULL,
  935.                                          &lpcm))
  936.   {
  937.  
  938.     cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
  939.     cmi.fMask = 0;
  940.     cmi.hwnd = GetParent(hwnd);
  941.     cmi.lpVerb = lpVerb;
  942.     cmi.lpParameters = NULL;
  943.     cmi.lpDirectory = NULL;
  944.     cmi.nShow = SW_SHOWNORMAL;
  945.     cmi.dwHotKey = 0;
  946.     cmi.hIcon = NULL;
  947.  
  948.     if (NOERROR != lpcm->lpVtbl->InvokeCommand(lpcm,&cmi))
  949.       bSuccess = FALSE;
  950.  
  951.     lpcm->lpVtbl->Release(lpcm);
  952.  
  953.   }
  954.  
  955.   else
  956.     bSuccess = FALSE;
  957.  
  958.   return(bSuccess);
  959.  
  960. }
  961.  
  962.  
  963.  
  964. //=============================================================================
  965. //
  966. //  DirList_DoDragDrop()
  967. //
  968. //  Execute an OLE Drag & Drop Operation in response to LVN_BEGIN(R)DRAG
  969. //
  970. //extern LPDROPSOURCE CreateDropSource();
  971.  
  972. void DirList_DoDragDrop(HWND hwnd,LPARAM lParam)
  973. {
  974.  
  975.   //LV_ITEM lvi;
  976.   //LPLV_ITEMDATA lplvid;
  977.   //LPDATAOBJECT lpdo;
  978.   //LPDROPSOURCE lpds;
  979.   //DWORD dwEffect;
  980.   //NM_LISTVIEW *pnmlv = (LPVOID)lParam;
  981.  
  982.   //lvi.iItem = pnmlv->iItem;
  983.   //lvi.iSubItem = 0;
  984.   //lvi.mask = LVIF_PARAM;
  985.  
  986.   //if (ListView_GetItem(hwnd,&lvi))
  987.   //{
  988.  
  989.   //  lplvid = (LPLV_ITEMDATA)lvi.lParam;
  990.  
  991.   //  if (SUCCEEDED(lplvid->lpsf->lpVtbl->GetUIObjectOf(
  992.   //                                        lplvid->lpsf,
  993.   //                                        GetParent(hwnd),
  994.   //                                        1,
  995.   //                                        &lplvid->pidl,
  996.   //                                        &IID_IDataObject,
  997.   //                                        NULL,
  998.   //                                        &lpdo)))
  999.   //  {
  1000.  
  1001.   //    lpds = CreateDropSource();
  1002.  
  1003.   //    DoDragDrop(lpdo,lpds,DROPEFFECT_COPY|DROPEFFECT_MOVE|DROPEFFECT_LINK,&dwEffect);
  1004.  
  1005.   //    lpdo->lpVtbl->Release(lpdo);
  1006.   //    lpds->lpVtbl->Release(lpds);
  1007.  
  1008.   //  }
  1009.   //}
  1010. }
  1011.  
  1012.  
  1013.  
  1014. //=============================================================================
  1015. //
  1016. //  DirList_GetLongPathName()
  1017. //
  1018. //  Get long pathname for currently displayed directory
  1019. //
  1020. BOOL DirList_GetLongPathName(HWND hwnd,LPSTR lpszLongPath)
  1021. {
  1022.   char tch[MAX_PATH];
  1023.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  1024.   if (SHGetPathFromIDList(lpdl->pidl,tch))
  1025.   {
  1026.     lstrcpy(lpszLongPath,tch);
  1027.     return(TRUE);
  1028.   }
  1029.   else
  1030.     return(FALSE);
  1031. }
  1032.  
  1033.  
  1034.  
  1035. //=============================================================================
  1036. //
  1037. //  DirList_SelectItem()
  1038. //
  1039. //  Select specified item in the list
  1040. //
  1041. BOOL DirList_SelectItem(HWND hwnd,LPCSTR lpszDisplayName,LPCSTR lpszFullPath)
  1042. {
  1043.  
  1044.   #define LVIS_FLAGS LVIS_SELECTED|LVIS_FOCUSED
  1045.  
  1046.   char szShortPath[MAX_PATH];
  1047.   SHFILEINFO  shfi;
  1048.  
  1049.   LV_FINDINFO lvfi;
  1050.   DLITEM dli;
  1051.  
  1052.   int i = -1;
  1053.  
  1054.   if (!lpszFullPath || !lstrlen(lpszFullPath))
  1055.     return(FALSE);
  1056.   else
  1057.     GetShortPathName(lpszFullPath,szShortPath,MAX_PATH);
  1058.  
  1059.   if (!lpszDisplayName || !lstrlen(lpszDisplayName))
  1060.     SHGetFileInfo(lpszFullPath,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME);
  1061.   else
  1062.     lstrcpyn(shfi.szDisplayName,lpszDisplayName,MAX_PATH);
  1063.  
  1064.   lvfi.flags = LVFI_STRING;
  1065.   lvfi.psz   = shfi.szDisplayName;
  1066.  
  1067.   dli.mask = DLI_ALL;
  1068.  
  1069.   while ((i = ListView_FindItem(hwnd,i,&lvfi)) != -1)
  1070.   {
  1071.  
  1072.     DirList_GetItem(hwnd,i,&dli);
  1073.     GetShortPathName(dli.szFileName,dli.szFileName,MAX_PATH);
  1074.  
  1075.     if (!lstrcmpi(dli.szFileName,szShortPath))
  1076.     {
  1077.       ListView_SetItemState(hwnd,i,LVIS_FLAGS,LVIS_FLAGS);
  1078.       ListView_EnsureVisible(hwnd,i,FALSE);
  1079.  
  1080.       return(TRUE);
  1081.     }
  1082.  
  1083.   }
  1084.  
  1085.   return(FALSE);
  1086.  
  1087. }
  1088.  
  1089.  
  1090.  
  1091. //=============================================================================
  1092. //
  1093. //  DirList_CreateFilter()
  1094. //
  1095. //  Create a valid DL_FILTER structure
  1096. //
  1097. void DirList_CreateFilter(PDL_FILTER pdlf,LPCSTR lpszFileSpec,
  1098.                           BOOL bExcludeFilter)
  1099. {
  1100.  
  1101.   char *p;
  1102.  
  1103.   ZeroMemory(pdlf,sizeof(DL_FILTER));
  1104.   lstrcpyn(pdlf->tFilterBuf,lpszFileSpec,(DL_FILTER_BUFSIZE-1));
  1105.   pdlf->bExcludeFilter = bExcludeFilter;
  1106.  
  1107.   if (!lstrcmp(lpszFileSpec,"*.*") || !lstrlen(lpszFileSpec))
  1108.     return;
  1109.  
  1110.   pdlf->nCount = 1;
  1111.   pdlf->pFilter[0] = &pdlf->tFilterBuf[0];    // Zeile zum Ausprobieren
  1112.  
  1113.   while (p = strchr(pdlf->pFilter[pdlf->nCount-1],';'))
  1114.   {
  1115.     *p = '\0';                              // Replace ';' by '\0'
  1116.     pdlf->pFilter[pdlf->nCount] = (p + 1);  // Next position after ';'
  1117.     pdlf->nCount++;                         // Increase number of filters
  1118.   }
  1119.  
  1120. }
  1121.  
  1122.  
  1123.  
  1124. //=============================================================================
  1125. //
  1126. //  DirList_MatchFilter()
  1127. //
  1128. //  Check if a specified item matches a given filter
  1129. //
  1130. BOOL DirList_MatchFilter(LPSHELLFOLDER lpsf,LPCITEMIDLIST pidl,PDL_FILTER pdlf)
  1131. {
  1132.  
  1133.   int i;
  1134.   WIN32_FIND_DATA fd;
  1135.   BOOL bMatchSpec;
  1136.  
  1137.   // Immediately return true if lpszFileSpec is *.* or NULL
  1138.   if (pdlf->nCount == 0 && !pdlf->bExcludeFilter)
  1139.     return TRUE;
  1140.  
  1141.   SHGetDataFromIDList(lpsf,pidl,SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA));
  1142.  
  1143.   // All the directories are added
  1144.   if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1145.     return(TRUE);
  1146.  
  1147.   // Check if exclude *.* after directories have been added
  1148.   if (pdlf->nCount == 0 && pdlf->bExcludeFilter)
  1149.     return FALSE;
  1150.  
  1151.   for (i = 0; i < pdlf->nCount; i++)
  1152.   {
  1153.     if (*pdlf->pFilter[i]) // Filters like "\0" are ignored
  1154.     {
  1155.       bMatchSpec = PathMatchSpec(fd.cFileName,pdlf->pFilter[i]);
  1156.       if (bMatchSpec)
  1157.       {
  1158.         if (!pdlf->bExcludeFilter)
  1159.           return(TRUE);
  1160.         else
  1161.           return(FALSE);
  1162.       }
  1163.     }
  1164.   }
  1165.  
  1166.   // No matching
  1167.   return(pdlf->bExcludeFilter)?TRUE:FALSE;
  1168.  
  1169. }
  1170.  
  1171.  
  1172.  
  1173. //==== DriveBox ===============================================================
  1174.  
  1175. //=============================================================================
  1176. //
  1177. //  Internal Itemdata Structure
  1178. //
  1179. typedef struct tagDC_ITEMDATA
  1180. {
  1181.  
  1182.   LPITEMIDLIST  pidl;
  1183.   LPSHELLFOLDER lpsf;
  1184.  
  1185. } DC_ITEMDATA, *LPDC_ITEMDATA;
  1186.  
  1187.  
  1188. //=============================================================================
  1189. //
  1190. //  DriveBox_Init()
  1191. //
  1192. //  Initializes the drive box
  1193. //
  1194. BOOL DriveBox_Init(HWND hwnd)
  1195. {
  1196.  
  1197.   HIMAGELIST hil;
  1198.   SHFILEINFO shfi;
  1199.  
  1200.   hil = (HIMAGELIST)SHGetFileInfo("C:\\",0,&shfi,sizeof(SHFILEINFO),
  1201.                                   SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  1202.   SendMessage(hwnd,CBEM_SETIMAGELIST,0,(LPARAM)hil);
  1203.   SendMessage(hwnd,CBEM_SETEXTENDEDSTYLE,CBES_EX_NOSIZELIMIT,CBES_EX_NOSIZELIMIT);
  1204.  
  1205.   return TRUE;
  1206.  
  1207. }
  1208.  
  1209.  
  1210. //=============================================================================
  1211. //
  1212. //  DriveBox_Fill
  1213. //
  1214.  
  1215. int DriveBox_Fill(HWND hwnd)
  1216. {
  1217.  
  1218.   //LPMALLOC lpMalloc;
  1219.  
  1220.   LPSHELLFOLDER lpsfDesktop;
  1221.   LPSHELLFOLDER lpsf; // Workspace == CSIDL_DRIVES
  1222.  
  1223.   LPITEMIDLIST  pidl;
  1224.   LPITEMIDLIST  pidlEntry;
  1225.  
  1226.   LPENUMIDLIST  lpe;
  1227.  
  1228.   COMBOBOXEXITEM  cbei;
  1229.   LPDC_ITEMDATA   lpdcid;
  1230.  
  1231.   ULONG dwAttributes = 0;
  1232.  
  1233.   DWORD grfFlags = SHCONTF_FOLDERS;
  1234.  
  1235.  
  1236.   // Init ComboBox
  1237.   SendMessage(hwnd,WM_SETREDRAW,0,0);
  1238.   SendMessage(hwnd,CB_RESETCONTENT,0,0);
  1239.  
  1240.   ZeroMemory(&cbei,sizeof(COMBOBOXEXITEM));
  1241.   cbei.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_LPARAM;
  1242.   cbei.pszText = LPSTR_TEXTCALLBACK;
  1243.   cbei.cchTextMax = MAX_PATH;
  1244.   cbei.iImage = I_IMAGECALLBACK;
  1245.   cbei.iSelectedImage = I_IMAGECALLBACK;
  1246.  
  1247.   // Get Shell's IMalloc Interface
  1248.   //if (NOERROR == SHGetMalloc(&lpMalloc))
  1249.   //{
  1250.  
  1251.     // Get pidl to [My Computer]
  1252.     if (NOERROR == SHGetSpecialFolderLocation(hwnd,
  1253.                                               CSIDL_DRIVES,
  1254.                                               &pidl))
  1255.     {
  1256.  
  1257.       // Get Desktop Folder
  1258.       if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
  1259.       {
  1260.  
  1261.         // Bind pidl to IShellFolder
  1262.         if (NOERROR == lpsfDesktop->lpVtbl->BindToObject(
  1263.                                               lpsfDesktop,
  1264.                                               pidl,
  1265.                                               NULL,
  1266.                                               &IID_IShellFolder,
  1267.                                               &lpsf))
  1268.  
  1269.         {
  1270.  
  1271.           // Create an Enumeration object for lpsf
  1272.           if (NOERROR == lpsf->lpVtbl->EnumObjects(
  1273.                                          lpsf,
  1274.                                          hwnd,
  1275.                                          grfFlags,
  1276.                                          &lpe))
  1277.  
  1278.           {
  1279.  
  1280.             // Enumerate the contents of [My Computer]
  1281.             while (NOERROR == lpe->lpVtbl->Next(
  1282.                                              lpe,
  1283.                                              1,
  1284.                                              &pidlEntry,
  1285.                                              NULL))
  1286.  
  1287.             {
  1288.  
  1289.               // Add item to the List if it is part of the
  1290.               // Filesystem
  1291.               dwAttributes = SFGAO_FILESYSTEM;
  1292.  
  1293.               lpsf->lpVtbl->GetAttributesOf(
  1294.                               lpsf,
  1295.                               1,
  1296.                               &pidlEntry,
  1297.                               &dwAttributes);
  1298.  
  1299.               if (dwAttributes & SFGAO_FILESYSTEM)
  1300.               {
  1301.  
  1302.                 // Windows XP: check if pidlEntry is a drive
  1303.                 SHDESCRIPTIONID di;
  1304.                 HRESULT hr;
  1305.                 hr = SHGetDataFromIDList(lpsf,pidlEntry,SHGDFIL_DESCRIPTIONID,
  1306.                                          &di,sizeof(SHDESCRIPTIONID));
  1307.                 if (hr != NOERROR || (di.dwDescriptionId >= SHDID_COMPUTER_DRIVE35 &&
  1308.                                       di.dwDescriptionId <= SHDID_COMPUTER_OTHER))
  1309.                 {
  1310.  
  1311.                   lpdcid = g_lpMalloc->lpVtbl->Alloc(
  1312.                                                 g_lpMalloc,
  1313.                                                 sizeof(DC_ITEMDATA));
  1314.  
  1315.                   //lpdcid->pidl = IL_Copy(lpMalloc,pidlEntry);
  1316.                   lpdcid->pidl = pidlEntry;
  1317.                   lpdcid->lpsf = lpsf;
  1318.  
  1319.                   lpsf->lpVtbl->AddRef(lpsf);
  1320.  
  1321.                   // Insert sorted ...
  1322.                   {
  1323.                     COMBOBOXEXITEM cbei2;
  1324.                     LPDC_ITEMDATA lpdcid2;
  1325.                     HRESULT hr;
  1326.                     cbei2.mask = CBEIF_LPARAM;
  1327.                     cbei2.iItem = 0;
  1328.  
  1329.                     while ((SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei2)))
  1330.                     {
  1331.                       lpdcid2 = (LPDC_ITEMDATA)cbei2.lParam;
  1332.                       hr = (lpdcid->lpsf->lpVtbl->CompareIDs(
  1333.                                  lpdcid->lpsf,
  1334.                                  0,
  1335.                                  lpdcid->pidl,
  1336.                                  lpdcid2->pidl));
  1337.  
  1338.                       if ((short)(SCODE_CODE(GetScode(hr))) < 0)
  1339.                         break;
  1340.                       else
  1341.                         cbei2.iItem++;
  1342.                     }
  1343.  
  1344.                     cbei.iItem = cbei2.iItem;
  1345.                     cbei.lParam = (LPARAM)lpdcid;
  1346.                     SendMessage(hwnd,CBEM_INSERTITEM,0,(LPARAM)&cbei);
  1347.  
  1348.                   }
  1349.  
  1350.                 }
  1351.  
  1352.               }
  1353.  
  1354.               //lpMalloc->lpVtbl->Free(lpMalloc,pidlEntry);
  1355.  
  1356.             } // IEnumIDList::Next()
  1357.  
  1358.             lpe->lpVtbl->Release(lpe);
  1359.  
  1360.           } // IShellFolder::EnumObjects()
  1361.  
  1362.           lpsf->lpVtbl->Release(lpsf);
  1363.  
  1364.         } // IShellFolder::BindToObject()
  1365.  
  1366.         g_lpMalloc->lpVtbl->Free(g_lpMalloc,pidl);
  1367.  
  1368.       } // SHGetSpecialFolderLocation()
  1369.  
  1370.       lpsfDesktop->lpVtbl->Release(lpsfDesktop);
  1371.  
  1372.     } // SHGetDesktopFolder()
  1373.  
  1374.     //lpMalloc->lpVtbl->Release(lpMalloc);
  1375.  
  1376.   //} // SHGetMalloc()
  1377.  
  1378.  
  1379.   SendMessage(hwnd,WM_SETREDRAW,1,0);
  1380.   // Return number of items added to combo box
  1381.   return (SendMessage(hwnd,CB_GETCOUNT,0,0));
  1382.  
  1383. }
  1384.  
  1385.  
  1386. //=============================================================================
  1387. //
  1388. //  DriveBox_GetSelDrive
  1389. //
  1390. BOOL DriveBox_GetSelDrive(HWND hwnd,LPSTR lpszDrive,int nDrive,BOOL fNoSlash)
  1391. {
  1392.  
  1393.   COMBOBOXEXITEM cbei;
  1394.   LPDC_ITEMDATA lpdcid;
  1395.   int i = SendMessage(hwnd,CB_GETCURSEL,0,0);
  1396.  
  1397.   // CB_ERR means no Selection
  1398.   if (i == CB_ERR)
  1399.     return FALSE;
  1400.  
  1401.   // Get DC_ITEMDATA* of selected Item
  1402.   cbei.mask = CBEIF_LPARAM;
  1403.   cbei.iItem = i;
  1404.   SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
  1405.   lpdcid = (LPDC_ITEMDATA)cbei.lParam;
  1406.  
  1407.   // Get File System Path for Drive
  1408.   IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,lpszDrive,nDrive);
  1409.  
  1410.   // Remove Backslash if required (makes Drive relative!!!)
  1411.   if (fNoSlash)
  1412.     PathRemoveBackslash(lpszDrive);
  1413.  
  1414.   return TRUE;
  1415.  
  1416. }
  1417.  
  1418.  
  1419. //=============================================================================
  1420. //
  1421. //  DriveBox_SelectDrive
  1422. //
  1423. BOOL DriveBox_SelectDrive(HWND hwnd,LPCSTR lpszPath)
  1424. {
  1425.  
  1426.   COMBOBOXEXITEM cbei;
  1427.   LPDC_ITEMDATA lpdcid;
  1428.   char szRoot[64];
  1429.  
  1430.   int i;
  1431.   int cbItems = SendMessage(hwnd,CB_GETCOUNT,0,0);
  1432.  
  1433.   // No Drives in Combo Box
  1434.   if (!cbItems)
  1435.     return FALSE;
  1436.  
  1437.   cbei.mask = CBEIF_LPARAM;
  1438.  
  1439.   for (i = 0; i < cbItems; i++)
  1440.   {
  1441.     // Get DC_ITEMDATA* of Item i
  1442.     cbei.iItem = i;
  1443.     SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
  1444.     lpdcid = (LPDC_ITEMDATA)cbei.lParam;
  1445.  
  1446.     // Get File System Path for Drive
  1447.     IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,szRoot,64);
  1448.  
  1449.     // Compare Root Directory with Path
  1450.     if (PathIsSameRoot(lpszPath,szRoot))
  1451.     {
  1452.       // Select matching Drive
  1453.       SendMessage(hwnd,CB_SETCURSEL,i,0);
  1454.       return TRUE;
  1455.     }
  1456.   }
  1457.  
  1458.   // Don't select anything
  1459.   SendMessage(hwnd,CB_SETCURSEL,(WPARAM)-1,0);
  1460.   return FALSE;
  1461.  
  1462. }
  1463.  
  1464.  
  1465. //=============================================================================
  1466. //
  1467. //  DriveBox_PropertyDlg()
  1468. //
  1469. //  Shows standard Win95 Property Dlg for selected Drive
  1470. //
  1471. BOOL DriveBox_PropertyDlg(HWND hwnd)
  1472. {
  1473.  
  1474.   COMBOBOXEXITEM cbei;
  1475.   LPDC_ITEMDATA lpdcid;
  1476.   int iItem;
  1477.   LPCONTEXTMENU lpcm;
  1478.   CMINVOKECOMMANDINFO cmi;
  1479.   BOOL bSuccess = TRUE;
  1480.  
  1481.   static const char *lpVerb = "properties";
  1482.  
  1483.   iItem = SendMessage(hwnd,CB_GETCURSEL,0,0);
  1484.  
  1485.   if (iItem == CB_ERR)
  1486.     return FALSE;
  1487.  
  1488.   cbei.mask = CBEIF_LPARAM;
  1489.   cbei.iItem = iItem;
  1490.   SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
  1491.   lpdcid = (LPDC_ITEMDATA)cbei.lParam;
  1492.  
  1493.   if (NOERROR == lpdcid->lpsf->lpVtbl->GetUIObjectOf(
  1494.                                          lpdcid->lpsf,
  1495.                                          GetParent(hwnd),  // Owner
  1496.                                          1,                // Number of objects
  1497.                                          &lpdcid->pidl,    // pidl
  1498.                                          &IID_IContextMenu,
  1499.                                          NULL,
  1500.                                          &lpcm))
  1501.   {
  1502.  
  1503.     cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
  1504.     cmi.fMask = 0;
  1505.     cmi.hwnd = GetParent(hwnd);
  1506.     cmi.lpVerb = lpVerb;
  1507.     cmi.lpParameters = NULL;
  1508.     cmi.lpDirectory = NULL;
  1509.     cmi.nShow = SW_SHOWNORMAL;
  1510.     cmi.dwHotKey = 0;
  1511.     cmi.hIcon = NULL;
  1512.  
  1513.     if (NOERROR != lpcm->lpVtbl->InvokeCommand(lpcm,&cmi))
  1514.       bSuccess = FALSE;
  1515.  
  1516.     lpcm->lpVtbl->Release(lpcm);
  1517.  
  1518.   }
  1519.  
  1520.   else
  1521.     bSuccess = FALSE;
  1522.  
  1523.   return(bSuccess);
  1524.  
  1525. }
  1526.  
  1527.  
  1528. //=============================================================================
  1529. //
  1530. //  DriveBox_DeleteItem
  1531. //
  1532. LRESULT DriveBox_DeleteItem(HWND hwnd,LPARAM lParam)
  1533. {
  1534.  
  1535.   //LPMALLOC lpMalloc;
  1536.   NMCOMBOBOXEX *lpnmcbe;
  1537.   COMBOBOXEXITEM cbei;
  1538.   LPDC_ITEMDATA lpdcid;
  1539.  
  1540.   lpnmcbe = (LPVOID)lParam;
  1541.   cbei.iItem = lpnmcbe->ceItem.iItem;
  1542.  
  1543.   cbei.mask = CBEIF_LPARAM;
  1544.   SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
  1545.   lpdcid = (LPDC_ITEMDATA)cbei.lParam;
  1546.  
  1547.   //SHGetMalloc(&lpMalloc);
  1548.  
  1549.   // Free pidl
  1550.   g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdcid->pidl);
  1551.   // Release lpsf
  1552.   lpdcid->lpsf->lpVtbl->Release(lpdcid->lpsf);
  1553.  
  1554.   // Free lpdcid itself
  1555.   g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdcid);
  1556.  
  1557.   // Release lpMalloc
  1558.   //lpMalloc->lpVtbl->Release(lpMalloc);
  1559.  
  1560.   return TRUE;
  1561.  
  1562. }
  1563.  
  1564.  
  1565. //=============================================================================
  1566. //
  1567. //  DriveBox_GetDispInfo
  1568. //
  1569. LRESULT DriveBox_GetDispInfo(HWND hwnd,LPARAM lParam)
  1570. {
  1571.  
  1572.   NMCOMBOBOXEX *lpnmcbe;
  1573.   LPDC_ITEMDATA lpdcid;
  1574.   SHFILEINFO shfi;
  1575.   char szTemp[256];
  1576.  
  1577.   lpnmcbe = (LPVOID)lParam;
  1578.   lpdcid = (LPDC_ITEMDATA)lpnmcbe->ceItem.lParam;
  1579.  
  1580.   if (!lpdcid)
  1581.     return FALSE;
  1582.  
  1583.   // Get Display Name
  1584.   if (lpnmcbe->ceItem.mask & CBEIF_TEXT)
  1585.     IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_NORMAL,lpnmcbe->ceItem.pszText,lpnmcbe->ceItem.cchTextMax);
  1586.  
  1587.   // Get Icon Index
  1588.   if (lpnmcbe->ceItem.mask & (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE))
  1589.   {
  1590.     IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,szTemp,256);
  1591.     SHGetFileInfo(szTemp,0,&shfi,sizeof(SHFILEINFO),SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  1592.     lpnmcbe->ceItem.iImage = shfi.iIcon;
  1593.     lpnmcbe->ceItem.iSelectedImage = shfi.iIcon;
  1594.   }
  1595.  
  1596.   // Set values
  1597.   lpnmcbe->ceItem.mask |= CBEIF_DI_SETITEM;
  1598.  
  1599.   return TRUE;
  1600.  
  1601. }
  1602.  
  1603.  
  1604.  
  1605. //==== ItemID =================================================================
  1606.  
  1607. //=============================================================================
  1608. //
  1609. //  IL_Create()
  1610. //
  1611. // Creates an ITEMIDLIST by concatenating pidl1 and pidl2
  1612. // cb1 and cb2 indicate the sizes of the pidls, where cb1
  1613. // can be zero and pidl1 can be NULL
  1614. //
  1615. // If cb2 is zero, the size of pidl2 is retrieved using
  1616. // IL_GetSize(pidl2)
  1617. //
  1618. LPITEMIDLIST IL_Create(LPMALLOC lpMalloc,
  1619.                        LPCITEMIDLIST pidl1,UINT cb1,
  1620.                        LPCITEMIDLIST pidl2,UINT cb2)
  1621. {
  1622.  
  1623.   LPITEMIDLIST pidl;
  1624.  
  1625.   if (!pidl2)
  1626.     return NULL;
  1627.  
  1628.   if (!cb2)
  1629.     cb2 = IL_GetSize(pidl2) + 2; // Space for terminating Bytes
  1630.  
  1631.   if (!cb1)
  1632.     cb1 = IL_GetSize(pidl1);
  1633.  
  1634.   // Allocate Memory
  1635.   pidl = lpMalloc->lpVtbl->Alloc(lpMalloc,cb1 + cb2);
  1636.  
  1637.   // Init new ITEMIDLIST
  1638.   if (pidl1)
  1639.     CopyMemory(pidl,pidl1,cb1);
  1640.  
  1641.   // pidl2 can't be NULL here
  1642.   CopyMemory((LPBYTE)pidl + cb1,pidl2,cb2);
  1643.  
  1644.   return pidl;
  1645.  
  1646. }
  1647.  
  1648.  
  1649. //=============================================================================
  1650. //
  1651. // IL_GetSize()
  1652. //
  1653. // Retrieves the number of bytes in a pidl
  1654. // Does not add space for zero terminators !!
  1655. //
  1656. UINT IL_GetSize(LPCITEMIDLIST pidl)
  1657. {
  1658.  
  1659.   LPITEMIDLIST pidlTmp;
  1660.   UINT cb = 0;
  1661.  
  1662.   if (!pidl)
  1663.     return 0;
  1664.  
  1665.   for (pidlTmp = (LPITEMIDLIST)pidl;
  1666.        pidlTmp->mkid.cb;
  1667.        pidlTmp = _IL_Next(pidlTmp))
  1668.  
  1669.     cb += pidlTmp->mkid.cb;
  1670.  
  1671.  
  1672.   return cb;
  1673.  
  1674. }
  1675.  
  1676.  
  1677. //=============================================================================
  1678. //
  1679. // IL_GetDisplayName()
  1680. //
  1681. // Gets the Display Name of a pidl. lpsf is the parent IShellFolder Interface
  1682. // dwFlags specify a SHGDN_xx value
  1683. //
  1684. BOOL IL_GetDisplayName(LPSHELLFOLDER lpsf,
  1685.                        LPCITEMIDLIST pidl,
  1686.                        DWORD dwFlags,
  1687.                        LPSTR lpszDisplayName,
  1688.                        int nDisplayName)
  1689. {
  1690.  
  1691.   STRRET str;
  1692.  
  1693.   if (NOERROR == lpsf->lpVtbl->GetDisplayNameOf(lpsf,
  1694.                                                 pidl,
  1695.                                                 dwFlags,
  1696.                                                 &str))
  1697.   {
  1698.  
  1699.     // Shlwapi.dll provides new function:
  1700.     // StrRetToBuf(&str,pidl,lpszDisplayName,nDisplayName);
  1701.     // ...but I suppose my version is faster ;-)
  1702.     switch (str.uType)
  1703.     {
  1704.  
  1705.       case STRRET_WSTR:
  1706.         WideCharToMultiByte(CP_ACP,
  1707.                             0,
  1708.                             str.pOleStr,
  1709.                             -1,
  1710.                             lpszDisplayName,
  1711.                             nDisplayName,
  1712.                             NULL,
  1713.                             NULL);
  1714.         g_lpMalloc->lpVtbl->Free(g_lpMalloc,str.pOleStr);
  1715.         break;
  1716.  
  1717.       case STRRET_OFFSET:
  1718.         lstrcpyn(lpszDisplayName,
  1719.                  ((char *)(pidl)) + str.uOffset,
  1720.                  nDisplayName);
  1721.         break;
  1722.  
  1723.       case STRRET_CSTR:
  1724.         lstrcpyn(lpszDisplayName,str.cStr,nDisplayName);
  1725.         break;
  1726.  
  1727.     }
  1728.  
  1729.     return TRUE;
  1730.   }
  1731.  
  1732.   return FALSE;
  1733. }
  1734.  
  1735.  
  1736.  
  1737. ///   End of Dlapi.c   \\\
  1738.