diff options
Diffstat (limited to 'src/Dlapi.c')
-rw-r--r-- | src/Dlapi.c | 1769 |
1 files changed, 1769 insertions, 0 deletions
diff --git a/src/Dlapi.c b/src/Dlapi.c new file mode 100644 index 0000000..139c731 --- /dev/null +++ b/src/Dlapi.c @@ -0,0 +1,1769 @@ +/******************************************************************************
+*
+*
+* Notepad2
+*
+* Dlapi.c
+* Directory Listing APIs used in Notepad2
+*
+* See Readme.txt for more information about this source code.
+* Please send me your comments to this work.
+*
+* See License.txt for details about distribution and modification.
+*
+* (c) Florian Balmer 1996-2010
+* florian.balmer@gmail.com
+* http://www.flos-freeware.ch
+*
+*
+******************************************************************************/
+#define _WIN32_WINNT 0x501
+#include <windows.h>
+#include <commctrl.h>
+#include <shlobj.h>
+#include <shlwapi.h>
+#include <string.h>
+#include "dlapi.h"
+
+
+
+//==== Global LPMALLOC instance ===============================================
+extern LPMALLOC g_lpMalloc;
+
+
+
+//==== DirList ================================================================
+
+//==== DLDATA Structure =======================================================
+
+typedef struct tagDLDATA // dl
+{
+
+ HWND hwnd; // HWND of ListView Control
+ UINT cbidl; // Size of pidl
+ LPITEMIDLIST pidl; // Directory Id
+ LPSHELLFOLDER lpsf; // IShellFolder Interface to pidl
+ WCHAR szPath[MAX_PATH]; // Pathname to Directory Id
+ int iDefIconFolder; // Default Folder Icon
+ int iDefIconFile; // Default File Icon
+ BOOL bNoFadeHidden; // Flag passed from GetDispInfo()
+ HANDLE hExitThread; // Flag is set when Icon Thread should terminate
+ HANDLE hTerminatedThread; // Flag is set when Icon Thread has terminated
+
+} DLDATA, *LPDLDATA;
+
+
+//==== Property Name ==========================================================
+static const WCHAR *pDirListProp = L"DirListData";
+
+
+
+//=============================================================================
+//
+// DirList_Init()
+//
+// Initializes the DLDATA structure and sets up the listview control
+//
+BOOL DirList_Init(HWND hwnd,LPCWSTR pszHeader)
+{
+
+ HIMAGELIST hil;
+ SHFILEINFO shfi;
+ LV_COLUMN lvc;
+
+ // Allocate DirListData Property
+ LPDLDATA lpdl = (LPVOID)GlobalAlloc(GPTR,sizeof(DLDATA));
+ SetProp(hwnd,pDirListProp,(HANDLE)lpdl);
+
+ // Setup dl
+ lpdl->hwnd = hwnd;
+ lpdl->cbidl = 0;
+ lpdl->pidl = NULL;
+ lpdl->lpsf = NULL;
+ lstrcpy(lpdl->szPath,L"");
+
+ // Add Imagelists
+ hil = (HIMAGELIST)SHGetFileInfo(L"C:\\",0,&shfi,sizeof(SHFILEINFO),
+ SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
+
+ ListView_SetImageList(hwnd,hil,LVSIL_SMALL);
+
+ hil = (HIMAGELIST)SHGetFileInfo(L"C:\\",0,&shfi,sizeof(SHFILEINFO),
+ SHGFI_LARGEICON | SHGFI_SYSICONINDEX);
+
+ ListView_SetImageList(hwnd,hil,LVSIL_NORMAL);
+
+ // Initialize default icons - done in DirList_Fill()
+ //SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
+ // SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
+ //lpdl->iDefIconFolder = shfi.iIcon;
+
+ //SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
+ // SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
+ //lpdl->iDefIconFile = shfi.iIcon;
+
+ lpdl->iDefIconFolder = 0;
+ lpdl->iDefIconFile = 0;
+
+ // Icon thread control
+ lpdl->hExitThread = CreateEvent(NULL,TRUE,FALSE,NULL);
+ lpdl->hTerminatedThread = CreateEvent(NULL,TRUE,TRUE,NULL);
+
+ lvc;
+ pszHeader;
+
+ return TRUE;
+
+}
+
+
+//=============================================================================
+//
+// DirList_Destroy()
+//
+// Free memory used by dl structure
+//
+BOOL DirList_Destroy(HWND hwnd)
+{
+
+ //LPMALLOC lpMalloc;
+
+ LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
+
+ // Release multithreading objects
+ DirList_TerminateIconThread(hwnd);
+ CloseHandle(lpdl->hExitThread);
+ CloseHandle(lpdl->hTerminatedThread);
+
+ //if (NOERROR == SHGetMalloc(&lpMalloc))
+ //{
+
+ if (lpdl->pidl)
+ g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdl->pidl);
+
+ //lpMalloc->lpVtbl->Release(lpMalloc);
+
+ if (lpdl->lpsf)
+ lpdl->lpsf->lpVtbl->Release(lpdl->lpsf);
+
+ //}
+
+ // Free DirListData Property
+ RemoveProp(hwnd,pDirListProp);
+ GlobalFree(lpdl);
+
+ return FALSE;
+
+}
+
+
+//=============================================================================
+//
+// DirList_StartIconThread()
+//
+// Start thread to extract file icons in the background
+//
+BOOL DirList_StartIconThread(HWND hwnd)
+{
+
+ DWORD dwtid;
+ LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
+
+ DirList_TerminateIconThread(hwnd);
+
+ ResetEvent(lpdl->hExitThread);
+ //ResetEvent(lpdl->hTerminatedThread);
+
+ CreateThread(NULL,0,DirList_IconThread,(LPVOID)lpdl,0,&dwtid);
+
+ return TRUE;
+
+}
+
+
+//=============================================================================
+//
+// DirList_TerminateIconThread()
+//
+// Terminate Icon Thread and reset multithreading control structures
+//
+BOOL DirList_TerminateIconThread(HWND hwnd)
+{
+
+ LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
+
+ SetEvent(lpdl->hExitThread);
+
+ //WaitForSingleObject(lpdl->hTerminatedThread,INFINITE);
+ while (WaitForSingleObject(lpdl->hTerminatedThread,0) != WAIT_OBJECT_0)
+ {
+ MSG msg;
+ if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ ResetEvent(lpdl->hExitThread);
+ SetEvent(lpdl->hTerminatedThread);
+
+ return TRUE;
+
+}
+
+
+//=============================================================================
+//
+// DirList_Fill()
+//
+// Snapshots a directory and displays the items in the listview control
+//
+int DirList_Fill(HWND hwnd,LPCWSTR lpszDir,DWORD grfFlags,LPCWSTR lpszFileSpec,
+ BOOL bExcludeFilter,BOOL bNoFadeHidden,
+ int iSortFlags,BOOL fSortRev)
+{
+
+ WCHAR wszDir[MAX_PATH];
+
+ //LPMALLOC lpMalloc = NULL;
+
+ LPSHELLFOLDER lpsfDesktop = NULL;
+ LPSHELLFOLDER lpsf = NULL;
+
+ LPITEMIDLIST pidl = NULL;
+ LPITEMIDLIST pidlEntry = NULL;
+
+ LPENUMIDLIST lpe = NULL;
+
+ LV_ITEM lvi;
+ LPLV_ITEMDATA lplvid;
+
+ ULONG chParsed = 0;
+ ULONG dwAttributes = 0;
+
+ DL_FILTER dlf;
+ SHFILEINFO shfi;
+
+ LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
+
+ // Initialize default icons
+ SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
+ SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
+ lpdl->iDefIconFolder = shfi.iIcon;
+
+ SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
+ SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
+ lpdl->iDefIconFile = shfi.iIcon;
+
+ // First of all terminate running icon thread
+ DirList_TerminateIconThread(hwnd);
+
+ // A Directory is strongly required
+ if (!lpszDir || !*lpszDir)
+ return(-1);
+
+ lstrcpy(lpdl->szPath,lpszDir);
+
+ // Init ListView
+ SendMessage(hwnd,WM_SETREDRAW,0,0);
+ ListView_DeleteAllItems(hwnd);
+
+ // Init Filter
+ DirList_CreateFilter(&dlf,lpszFileSpec,bExcludeFilter);
+
+ // Init lvi
+ lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
+ lvi.iItem = 0;
+ lvi.iSubItem = 0;
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.cchTextMax = MAX_PATH;
+ lvi.iImage = I_IMAGECALLBACK;
+
+ // Convert Directory to a UNICODE string
+ /*MultiByteToWideChar(CP_ACP,
+ MB_PRECOMPOSED,
+ lpszDir,
+ -1,
+ wszDir,
+ MAX_PATH);*/
+ lstrcpy(wszDir,lpszDir);
+
+
+ // Get Shell's IMalloc Interface
+ //if (NOERROR == SHGetMalloc(&lpMalloc))
+ //{
+
+ // Get Desktop Folder
+ if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
+ {
+
+ // Convert wszDir into a pidl
+ if (NOERROR == lpsfDesktop->lpVtbl->ParseDisplayName(
+ lpsfDesktop,
+ hwnd,
+ NULL,
+ wszDir,
+ &chParsed,
+ &pidl,
+ &dwAttributes))
+
+ {
+
+ // Bind pidl to IShellFolder
+ if (NOERROR == lpsfDesktop->lpVtbl->BindToObject(
+ lpsfDesktop,
+ pidl,
+ NULL,
+ &IID_IShellFolder,
+ &lpsf))
+
+ {
+
+ // Create an Enumeration object for lpsf
+ if (NOERROR == lpsf->lpVtbl->EnumObjects(
+ lpsf,
+ hwnd,
+ grfFlags,
+ &lpe))
+
+ {
+
+ // Enumerate the contents of lpsf
+ while (NOERROR == lpe->lpVtbl->Next(
+ lpe,
+ 1,
+ &pidlEntry,
+ NULL))
+
+ {
+
+ // Add found item to the List
+ // Check if it's part of the Filesystem
+ dwAttributes = SFGAO_FILESYSTEM | SFGAO_FOLDER;
+
+ lpsf->lpVtbl->GetAttributesOf(
+ lpsf,
+ 1,
+ &pidlEntry,
+ &dwAttributes);
+
+ if (dwAttributes & SFGAO_FILESYSTEM)
+ {
+
+ // Check if item matches specified filter
+ if (DirList_MatchFilter(lpsf,pidlEntry,&dlf))
+ {
+
+ lplvid = g_lpMalloc->lpVtbl->Alloc(
+ g_lpMalloc,
+ sizeof(LV_ITEMDATA));
+
+ lplvid->pidl = pidlEntry;
+ lplvid->lpsf = lpsf;
+
+ lpsf->lpVtbl->AddRef(lpsf);
+
+ lvi.lParam = (LPARAM)lplvid;
+
+ // Setup default Icon - Folder or File
+ lvi.iImage = (dwAttributes & SFGAO_FOLDER) ?
+ lpdl->iDefIconFolder : lpdl->iDefIconFile;
+
+ ListView_InsertItem(hwnd,&lvi);
+
+ lvi.iItem++;
+
+ }
+
+ }
+
+ //lpMalloc->lpVtbl->Free(lpMalloc,pidlEntry);
+
+ } // IEnumIDList::Next()
+
+ lpe->lpVtbl->Release(lpe);
+
+ } // IShellFolder::EnumObjects()
+
+ } // IShellFolder::BindToObject()
+
+ } // IShellFolder::ParseDisplayName()
+
+ lpsfDesktop->lpVtbl->Release(lpsfDesktop);
+
+ } // SHGetDesktopFolder()
+
+ if (lpdl->pidl)
+ g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdl->pidl);
+
+ if (lpdl->lpsf && lpdl->lpsf->lpVtbl)
+ lpdl->lpsf->lpVtbl->Release(lpdl->lpsf);
+
+ //lpMalloc->lpVtbl->Release(lpMalloc);
+
+ //} // SHGetMalloc()
+
+ // Set lpdl
+ lpdl->cbidl = IL_GetSize(pidl);
+ lpdl->pidl = pidl;
+ lpdl->lpsf = lpsf;
+ lpdl->bNoFadeHidden = bNoFadeHidden;
+
+ // Set column width to fit window
+ ListView_SetColumnWidth(hwnd,0,LVSCW_AUTOSIZE_USEHEADER);
+
+ // Sort before display is updated
+ DirList_Sort(hwnd,iSortFlags,fSortRev);
+
+ // Redraw Listview
+ SendMessage(hwnd,WM_SETREDRAW,1,0);
+
+ // Return number of items in the control
+ return (ListView_GetItemCount(hwnd));
+
+}
+
+
+//=============================================================================
+//
+// DirList_IconThread()
+//
+// Thread to extract file icons in the background
+//
+DWORD WINAPI DirList_IconThread(LPVOID lpParam)
+{
+
+ HWND hwnd;
+
+ LPDLDATA lpdl;
+ LV_ITEM lvi;
+ LPLV_ITEMDATA lplvid;
+
+ LPMALLOC lpMalloc;
+ IShellIcon* lpshi;
+
+ int iItem = 0;
+ int iMaxItem;
+
+ lpdl = (LPDLDATA)lpParam;
+ ResetEvent(lpdl->hTerminatedThread);
+
+ // Exit immediately if DirList_Fill() hasn't been called
+ if (!lpdl->lpsf) {
+ SetEvent(lpdl->hTerminatedThread);
+ ExitThread(0);
+ return(0);
+ }
+
+ hwnd = lpdl->hwnd;
+ iMaxItem = ListView_GetItemCount(hwnd);
+
+ CoInitialize(NULL);
+ SHGetMalloc(&lpMalloc);
+
+ // Get IShellIcon
+ lpdl->lpsf->lpVtbl->QueryInterface(lpdl->lpsf,&IID_IShellIcon,&lpshi);
+
+ while (iItem < iMaxItem && WaitForSingleObject(lpdl->hExitThread,0) != WAIT_OBJECT_0) {
+
+ lvi.iItem = iItem;
+ lvi.mask = LVIF_PARAM;
+ if (ListView_GetItem(hwnd,&lvi)) {
+
+ SHFILEINFO shfi;
+ LPITEMIDLIST pidl;
+ DWORD dwAttributes = SFGAO_LINK | SFGAO_SHARE;
+
+ lplvid = (LPLV_ITEMDATA)lvi.lParam;
+
+ lvi.mask = LVIF_IMAGE;
+
+ if (!lpshi || NOERROR != lpshi->lpVtbl->GetIconOf(lpshi,lplvid->pidl,GIL_FORSHELL,&lvi.iImage))
+ {
+ pidl = IL_Create(lpMalloc,lpdl->pidl,lpdl->cbidl,lplvid->pidl,0);
+ SHGetFileInfo((LPCWSTR)pidl,0,&shfi,sizeof(SHFILEINFO),SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
+ lpMalloc->lpVtbl->Free(lpMalloc,pidl);
+ lvi.iImage = shfi.iIcon;
+ }
+
+ // It proved necessary to reset the state bits...
+ lvi.stateMask = 0;
+ lvi.state = 0;
+
+ // Link and Share Overlay
+ lplvid->lpsf->lpVtbl->GetAttributesOf(
+ lplvid->lpsf,
+ 1,&lplvid->pidl,
+ &dwAttributes);
+
+ if (dwAttributes & SFGAO_LINK)
+ {
+ lvi.mask |= LVIF_STATE;
+ lvi.stateMask |= LVIS_OVERLAYMASK;
+ lvi.state |= INDEXTOOVERLAYMASK(2);
+ }
+
+ if (dwAttributes & SFGAO_SHARE)
+ {
+ lvi.mask |= LVIF_STATE;
+ lvi.stateMask |= LVIS_OVERLAYMASK;
+ lvi.state |= INDEXTOOVERLAYMASK(1);
+ }
+
+ // Fade hidden/system files
+ if (!lpdl->bNoFadeHidden)
+ {
+ WIN32_FIND_DATA fd;
+ if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,lplvid->pidl,
+ SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA)))
+ {
+ if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
+ (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
+ {
+ lvi.mask |= LVIF_STATE;
+ lvi.stateMask |= LVIS_CUT;
+ lvi.state |= LVIS_CUT;
+ }
+ }
+ }
+ lvi.iSubItem = 0;
+ ListView_SetItem(hwnd,&lvi);
+ }
+ iItem++;
+ }
+
+ if (lpshi)
+ lpshi->lpVtbl->Release(lpshi);
+
+ lpMalloc->lpVtbl->Release(lpMalloc);
+ CoUninitialize();
+
+ SetEvent(lpdl->hTerminatedThread);
+ ExitThread(0);
+ return(0);
+
+}
+
+
+//=============================================================================
+//
+// DirList_GetDispInfo()
+//
+// Must be called in response to a WM_NOTIFY/LVN_GETDISPINFO message from
+// the listview control
+//
+BOOL DirList_GetDispInfo(HWND hwnd,LPARAM lParam,BOOL bNoFadeHidden)
+{
+
+ LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
+
+ LV_DISPINFO *lpdi = (LPVOID)lParam;
+
+ LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lpdi->item.lParam;
+
+ // SubItem 0 is handled only
+ if (lpdi->item.iSubItem != 0)
+ return FALSE;
+
+ // Text
+ if (lpdi->item.mask & LVIF_TEXT)
+ IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_INFOLDER,
+ lpdi->item.pszText,lpdi->item.cchTextMax);
+
+ // Image
+ //if (lpdi->item.mask & LVIF_IMAGE)
+ //{
+
+ // //LPMALLOC lpMalloc;
+ // SHFILEINFO shfi;
+ // LPITEMIDLIST pidl;
+ // DWORD dwAttributes = SFGAO_LINK | SFGAO_SHARE;
+
+ // //if (NOERROR == SHGetMalloc(&lpMalloc))
+ // //{
+
+ // // Generate Full Qualified pidl
+ // pidl = IL_Create(g_lpMalloc,lpdl->pidl,lpdl->cbidl,lplvid->pidl,0);
+
+ // SHGetFileInfo((LPCWSTR)pidl,0,&shfi,sizeof(SHFILEINFO),SHGFI_PIDL | SHGFI_SYSICONINDEX);
+
+ // lpdi->item.iImage = shfi.iIcon;
+
+ // g_lpMalloc->lpVtbl->Free(g_lpMalloc,pidl);
+ // //lpMalloc->lpVtbl->Release(lpMalloc);
+
+ // //}
+
+ // // It proved necessary to reset the state bits...
+ // lpdi->item.stateMask = 0;
+ // lpdi->item.state = 0;
+
+ // // Link and Share Overlay
+ // lplvid->lpsf->lpVtbl->GetAttributesOf(
+ // lplvid->lpsf,
+ // 1,&lplvid->pidl,
+ // &dwAttributes);
+
+ // if (dwAttributes & SFGAO_LINK)
+ // {
+ // lpdi->item.mask |= LVIF_STATE;
+ // lpdi->item.stateMask |= LVIS_OVERLAYMASK;
+ // lpdi->item.state |= INDEXTOOVERLAYMASK(2);
+ // }
+
+ // if (dwAttributes & SFGAO_SHARE)
+ // {
+ // lpdi->item.mask |= LVIF_STATE;
+ // lpdi->item.stateMask |= LVIS_OVERLAYMASK;
+ // lpdi->item.state |= INDEXTOOVERLAYMASK(1);
+ // }
+
+ // // Fade hidden/system files
+ // if (!bNoFadeHidden)
+ // {
+ // WIN32_FIND_DATA fd;
+ // if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,lplvid->pidl,
+ // SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA)))
+ // {
+ // if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
+ // (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
+ // {
+ // lpdi->item.mask |= LVIF_STATE;
+ // lpdi->item.stateMask |= LVIS_CUT;
+ // lpdi->item.state |= LVIS_CUT;
+ // }
+ // }
+
+ // }
+
+ //}
+
+ // Set values
+ lpdi->item.mask |= LVIF_DI_SETITEM;
+
+ return TRUE;
+
+}
+
+
+//=============================================================================
+//
+// DirList_DeleteItem()
+//
+// Must be called in response to a WM_NOTIFY/LVN_DELETEITEM message
+// from the control
+//
+BOOL DirList_DeleteItem(HWND hwnd,LPARAM lParam)
+{
+
+ LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
+
+ LV_ITEM lvi;
+ //LPMALLOC lpMalloc;
+
+ NM_LISTVIEW *lpnmlv = (LPVOID)lParam;
+
+ lvi.iItem = lpnmlv->iItem;
+ lvi.iSubItem = 0;
+ lvi.mask = LVIF_PARAM;
+
+ if (ListView_GetItem(hwnd,&lvi))
+ {
+
+ //if (NOERROR == SHGetMalloc(&lpMalloc))
+ //{
+
+ // Free mem
+ LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lvi.lParam;
+ g_lpMalloc->lpVtbl->Free(g_lpMalloc,lplvid->pidl);
+ lplvid->lpsf->lpVtbl->Release(lplvid->lpsf);
+
+ g_lpMalloc->lpVtbl->Free(g_lpMalloc,lplvid);
+
+ //lpMalloc->lpVtbl->Release(lpMalloc);
+
+ return TRUE;
+
+ //}
+
+ }
+
+ else
+ return FALSE;
+
+}
+
+
+//=============================================================================
+//
+// DirList_CompareProc()
+//
+// Compares two list items
+//
+int CALLBACK DirList_CompareProcFw(LPARAM lp1,LPARAM lp2,LPARAM lFlags)
+{
+
+ HRESULT hr;
+ int result;
+
+ LPLV_ITEMDATA lplvid1 = (LPLV_ITEMDATA)lp1;
+ LPLV_ITEMDATA lplvid2 = (LPLV_ITEMDATA)lp2;
+
+ hr = (lplvid1->lpsf->lpVtbl->CompareIDs(
+ lplvid1->lpsf,
+ lFlags,
+ lplvid1->pidl,
+ lplvid2->pidl));
+
+ result = (short)(SCODE_CODE(GetScode(hr)));
+
+ if (result != 0 || lFlags == 0)
+ return(result);
+
+ hr = (lplvid1->lpsf->lpVtbl->CompareIDs(
+ lplvid1->lpsf,
+ 0,
+ lplvid1->pidl,
+ lplvid2->pidl));
+
+ result = (short)(SCODE_CODE(GetScode(hr)));
+
+ return(result);
+
+}
+
+int CALLBACK DirList_CompareProcRw(LPARAM lp1,LPARAM lp2,LPARAM lFlags)
+{
+
+ HRESULT hr;
+ int result;
+
+ LPLV_ITEMDATA lplvid1 = (LPLV_ITEMDATA)lp1;
+ LPLV_ITEMDATA lplvid2 = (LPLV_ITEMDATA)lp2;
+
+ hr = (lplvid1->lpsf->lpVtbl->CompareIDs(
+ lplvid1->lpsf,
+ lFlags,
+ lplvid1->pidl,
+ lplvid2->pidl));
+
+ result = -(short)(SCODE_CODE(GetScode(hr)));
+
+ if (result != 0)
+ return(result);
+
+ hr = (lplvid1->lpsf->lpVtbl->CompareIDs(
+ lplvid1->lpsf,
+ 0,
+ lplvid1->pidl,
+ lplvid2->pidl));
+
+ result = -(short)(SCODE_CODE(GetScode(hr)));
+
+ return(result);
+
+}
+
+
+//=============================================================================
+//
+// DirList_Sort()
+//
+// Sorts the listview control by the specified order
+//
+BOOL DirList_Sort(HWND hwnd,int lFlags,BOOL fRev)
+{
+
+ LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
+
+ if (fRev)
+
+ return ListView_SortItems(hwnd,DirList_CompareProcRw,lFlags);
+
+ else
+
+ return ListView_SortItems(hwnd,DirList_CompareProcFw,lFlags);
+
+}
+
+
+//=============================================================================
+//
+// DirList_GetItem()
+//
+// Copies the data of the specified item in the listview control to a buffer
+//
+int DirList_GetItem(HWND hwnd,int iItem,LPDLITEM lpdli)
+{
+
+ LV_ITEM lvi;
+ LPLV_ITEMDATA lplvid;
+
+ ULONG dwAttributes = SFGAO_FILESYSTEM;
+
+
+ if (iItem == -1)
+ {
+
+ if (ListView_GetSelectedCount(hwnd))
+
+ iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
+
+ else
+
+ return(-1);
+
+ }
+
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = iItem;
+ lvi.iSubItem = 0;
+
+ if (!ListView_GetItem(hwnd,&lvi))
+ {
+
+ if (lpdli->mask & DLI_TYPE)
+
+ lpdli->ntype = DLE_NONE;
+
+ return(-1);
+
+ }
+
+ lplvid = (LPLV_ITEMDATA)lvi.lParam;
+
+ // Filename
+ if (lpdli->mask & DLI_FILENAME)
+
+ IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_FORPARSING,
+ lpdli->szFileName,MAX_PATH);
+
+ // Displayname
+ if (lpdli->mask & DLI_DISPNAME)
+
+ IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_INFOLDER,
+ lpdli->szDisplayName,MAX_PATH);
+
+ // Type (File / Directory)
+ if (lpdli->mask & DLI_TYPE)
+ {
+
+ WIN32_FIND_DATA fd;
+
+ if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,
+ lplvid->pidl,
+ SHGDFIL_FINDDATA,
+ &fd,
+ sizeof(WIN32_FIND_DATA)))
+
+ lpdli->ntype = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
+ DLE_DIR : DLE_FILE;
+
+ /*lplvid->lpsf->lpVtbl->GetAttributesOf(
+ lplvid->lpsf,
+ 1,
+ &lplvid->pidl,
+ &dwAttributes);
+
+ lpdli->ntype = (dwAttributes & SFGAO_FOLDER) ? DLE_DIR : DLE_FILE;*/
+
+ }
+
+ return iItem;
+
+}
+
+
+//=============================================================================
+//
+// DirList_GetItemEx()
+//
+// Retrieves extended infomration on a dirlist item
+//
+int DirList_GetItemEx(HWND hwnd,int iItem,LPWIN32_FIND_DATA pfd)
+{
+
+ LV_ITEM lvi;
+ LPLV_ITEMDATA lplvid;
+
+
+ if (iItem == -1)
+ {
+
+ if (ListView_GetSelectedCount(hwnd))
+
+ iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
+
+ else
+
+ return(-1);
+
+ }
+
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = iItem;
+ lvi.iSubItem = 0;
+
+ if (!ListView_GetItem(hwnd,&lvi))
+ return(-1);
+
+ lplvid = (LPLV_ITEMDATA)lvi.lParam;
+
+ if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,
+ lplvid->pidl,
+ SHGDFIL_FINDDATA,
+ pfd,
+ sizeof(WIN32_FIND_DATA)))
+ return iItem;
+
+ else
+ return(-1);
+
+}
+
+
+//=============================================================================
+//
+// DirList_PropertyDlg()
+//
+// Shows standard Win95 Property Dlg for selected Item
+//
+BOOL DirList_PropertyDlg(HWND hwnd,int iItem)
+{
+
+ LV_ITEM lvi;
+ LPLV_ITEMDATA lplvid;
+ LPCONTEXTMENU lpcm;
+ CMINVOKECOMMANDINFO cmi;
+ BOOL bSuccess = TRUE;
+
+ static const char *lpVerb = "properties";
+
+ if (iItem == -1)
+ {
+ if (ListView_GetSelectedCount(hwnd))
+ iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
+
+ else
+ return FALSE;
+ }
+
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = iItem;
+ lvi.iSubItem = 0;
+
+ if (!ListView_GetItem(hwnd,&lvi))
+ return FALSE;
+
+ lplvid = (LPLV_ITEMDATA)lvi.lParam;
+
+ if (NOERROR == lplvid->lpsf->lpVtbl->GetUIObjectOf(
+ lplvid->lpsf,
+ GetParent(hwnd), // Owner
+ 1, // Number of objects
+ &lplvid->pidl, // pidl
+ &IID_IContextMenu,
+ NULL,
+ &lpcm))
+ {
+
+ cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
+ cmi.fMask = 0;
+ cmi.hwnd = GetParent(hwnd);
+ cmi.lpVerb = lpVerb;
+ cmi.lpParameters = NULL;
+ cmi.lpDirectory = NULL;
+ cmi.nShow = SW_SHOWNORMAL;
+ cmi.dwHotKey = 0;
+ cmi.hIcon = NULL;
+
+ if (NOERROR != lpcm->lpVtbl->InvokeCommand(lpcm,&cmi))
+ bSuccess = FALSE;
+
+ lpcm->lpVtbl->Release(lpcm);
+
+ }
+
+ else
+ bSuccess = FALSE;
+
+ return(bSuccess);
+
+}
+
+
+
+//=============================================================================
+//
+// DirList_DoDragDrop()
+//
+// Execute an OLE Drag & Drop Operation in response to LVN_BEGIN(R)DRAG
+//
+//extern LPDROPSOURCE CreateDropSource();
+
+void DirList_DoDragDrop(HWND hwnd,LPARAM lParam)
+{
+
+ //LV_ITEM lvi;
+ //LPLV_ITEMDATA lplvid;
+ //LPDATAOBJECT lpdo;
+ //LPDROPSOURCE lpds;
+ //DWORD dwEffect;
+ //NM_LISTVIEW *pnmlv = (LPVOID)lParam;
+
+ //lvi.iItem = pnmlv->iItem;
+ //lvi.iSubItem = 0;
+ //lvi.mask = LVIF_PARAM;
+
+ //if (ListView_GetItem(hwnd,&lvi))
+ //{
+
+ // lplvid = (LPLV_ITEMDATA)lvi.lParam;
+
+ // if (SUCCEEDED(lplvid->lpsf->lpVtbl->GetUIObjectOf(
+ // lplvid->lpsf,
+ // GetParent(hwnd),
+ // 1,
+ // &lplvid->pidl,
+ // &IID_IDataObject,
+ // NULL,
+ // &lpdo)))
+ // {
+
+ // lpds = CreateDropSource();
+
+ // DoDragDrop(lpdo,lpds,DROPEFFECT_COPY|DROPEFFECT_MOVE|DROPEFFECT_LINK,&dwEffect);
+
+ // lpdo->lpVtbl->Release(lpdo);
+ // lpds->lpVtbl->Release(lpds);
+
+ // }
+ //}
+}
+
+
+
+//=============================================================================
+//
+// DirList_GetLongPathName()
+//
+// Get long pathname for currently displayed directory
+//
+BOOL DirList_GetLongPathName(HWND hwnd,LPWSTR lpszLongPath)
+{
+ WCHAR tch[MAX_PATH];
+ LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
+ if (SHGetPathFromIDList(lpdl->pidl,tch))
+ {
+ lstrcpy(lpszLongPath,tch);
+ return(TRUE);
+ }
+ else
+ return(FALSE);
+}
+
+
+
+//=============================================================================
+//
+// DirList_SelectItem()
+//
+// Select specified item in the list
+//
+BOOL DirList_SelectItem(HWND hwnd,LPCWSTR lpszDisplayName,LPCWSTR lpszFullPath)
+{
+
+ #define LVIS_FLAGS LVIS_SELECTED|LVIS_FOCUSED
+
+ WCHAR szShortPath[MAX_PATH];
+ SHFILEINFO shfi;
+
+ LV_FINDINFO lvfi;
+ DLITEM dli;
+
+ int i = -1;
+
+ if (!lpszFullPath || !lstrlen(lpszFullPath))
+ return(FALSE);
+ else
+ GetShortPathName(lpszFullPath,szShortPath,MAX_PATH);
+
+ if (!lpszDisplayName || !lstrlen(lpszDisplayName))
+ SHGetFileInfo(lpszFullPath,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME);
+ else
+ lstrcpyn(shfi.szDisplayName,lpszDisplayName,MAX_PATH);
+
+ lvfi.flags = LVFI_STRING;
+ lvfi.psz = shfi.szDisplayName;
+
+ dli.mask = DLI_ALL;
+
+ while ((i = ListView_FindItem(hwnd,i,&lvfi)) != -1)
+ {
+
+ DirList_GetItem(hwnd,i,&dli);
+ GetShortPathName(dli.szFileName,dli.szFileName,MAX_PATH);
+
+ if (!lstrcmpi(dli.szFileName,szShortPath))
+ {
+ ListView_SetItemState(hwnd,i,LVIS_FLAGS,LVIS_FLAGS);
+ ListView_EnsureVisible(hwnd,i,FALSE);
+
+ return(TRUE);
+ }
+
+ }
+
+ return(FALSE);
+
+}
+
+
+
+//=============================================================================
+//
+// DirList_CreateFilter()
+//
+// Create a valid DL_FILTER structure
+//
+void DirList_CreateFilter(PDL_FILTER pdlf,LPCWSTR lpszFileSpec,
+ BOOL bExcludeFilter)
+{
+
+ WCHAR *p;
+
+ ZeroMemory(pdlf,sizeof(DL_FILTER));
+ lstrcpyn(pdlf->tFilterBuf,lpszFileSpec,(DL_FILTER_BUFSIZE-1));
+ pdlf->bExcludeFilter = bExcludeFilter;
+
+ if (!lstrcmp(lpszFileSpec,L"*.*") || !lstrlen(lpszFileSpec))
+ return;
+
+ pdlf->nCount = 1;
+ pdlf->pFilter[0] = &pdlf->tFilterBuf[0]; // Zeile zum Ausprobieren
+
+ while (p = StrChr(pdlf->pFilter[pdlf->nCount-1],L';'))
+ {
+ *p = L'\0'; // Replace L';' by L'\0'
+ pdlf->pFilter[pdlf->nCount] = (p + 1); // Next position after L';'
+ pdlf->nCount++; // Increase number of filters
+ }
+
+}
+
+
+
+//=============================================================================
+//
+// DirList_MatchFilter()
+//
+// Check if a specified item matches a given filter
+//
+BOOL DirList_MatchFilter(LPSHELLFOLDER lpsf,LPCITEMIDLIST pidl,PDL_FILTER pdlf)
+{
+
+ int i;
+ WIN32_FIND_DATA fd;
+ BOOL bMatchSpec;
+
+ // Immediately return true if lpszFileSpec is *.* or NULL
+ if (pdlf->nCount == 0 && !pdlf->bExcludeFilter)
+ return TRUE;
+
+ SHGetDataFromIDList(lpsf,pidl,SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA));
+
+ // All the directories are added
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ return(TRUE);
+
+ // Check if exclude *.* after directories have been added
+ if (pdlf->nCount == 0 && pdlf->bExcludeFilter)
+ return FALSE;
+
+ for (i = 0; i < pdlf->nCount; i++)
+ {
+ if (*pdlf->pFilter[i]) // Filters like L"\0" are ignored
+ {
+ bMatchSpec = PathMatchSpec(fd.cFileName,pdlf->pFilter[i]);
+ if (bMatchSpec)
+ {
+ if (!pdlf->bExcludeFilter)
+ return(TRUE);
+ else
+ return(FALSE);
+ }
+ }
+ }
+
+ // No matching
+ return(pdlf->bExcludeFilter)?TRUE:FALSE;
+
+}
+
+
+
+//==== DriveBox ===============================================================
+
+//=============================================================================
+//
+// Internal Itemdata Structure
+//
+typedef struct tagDC_ITEMDATA
+{
+
+ LPITEMIDLIST pidl;
+ LPSHELLFOLDER lpsf;
+
+} DC_ITEMDATA, *LPDC_ITEMDATA;
+
+
+//=============================================================================
+//
+// DriveBox_Init()
+//
+// Initializes the drive box
+//
+BOOL DriveBox_Init(HWND hwnd)
+{
+
+ HIMAGELIST hil;
+ SHFILEINFO shfi;
+
+ hil = (HIMAGELIST)SHGetFileInfo(L"C:\\",0,&shfi,sizeof(SHFILEINFO),
+ SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
+ SendMessage(hwnd,CBEM_SETIMAGELIST,0,(LPARAM)hil);
+ SendMessage(hwnd,CBEM_SETEXTENDEDSTYLE,CBES_EX_NOSIZELIMIT,CBES_EX_NOSIZELIMIT);
+
+ return TRUE;
+
+}
+
+
+//=============================================================================
+//
+// DriveBox_Fill
+//
+
+int DriveBox_Fill(HWND hwnd)
+{
+
+ //LPMALLOC lpMalloc;
+
+ LPSHELLFOLDER lpsfDesktop;
+ LPSHELLFOLDER lpsf; // Workspace == CSIDL_DRIVES
+
+ LPITEMIDLIST pidl;
+ LPITEMIDLIST pidlEntry;
+
+ LPENUMIDLIST lpe;
+
+ COMBOBOXEXITEM cbei;
+ LPDC_ITEMDATA lpdcid;
+
+ ULONG dwAttributes = 0;
+
+ DWORD grfFlags = SHCONTF_FOLDERS;
+
+
+ // Init ComboBox
+ SendMessage(hwnd,WM_SETREDRAW,0,0);
+ SendMessage(hwnd,CB_RESETCONTENT,0,0);
+
+ ZeroMemory(&cbei,sizeof(COMBOBOXEXITEM));
+ cbei.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_LPARAM;
+ cbei.pszText = LPSTR_TEXTCALLBACK;
+ cbei.cchTextMax = MAX_PATH;
+ cbei.iImage = I_IMAGECALLBACK;
+ cbei.iSelectedImage = I_IMAGECALLBACK;
+
+ // Get Shell's IMalloc Interface
+ //if (NOERROR == SHGetMalloc(&lpMalloc))
+ //{
+
+ // Get pidl to [My Computer]
+ if (NOERROR == SHGetSpecialFolderLocation(hwnd,
+ CSIDL_DRIVES,
+ &pidl))
+ {
+
+ // Get Desktop Folder
+ if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
+ {
+
+ // Bind pidl to IShellFolder
+ if (NOERROR == lpsfDesktop->lpVtbl->BindToObject(
+ lpsfDesktop,
+ pidl,
+ NULL,
+ &IID_IShellFolder,
+ &lpsf))
+
+ {
+
+ // Create an Enumeration object for lpsf
+ if (NOERROR == lpsf->lpVtbl->EnumObjects(
+ lpsf,
+ hwnd,
+ grfFlags,
+ &lpe))
+
+ {
+
+ // Enumerate the contents of [My Computer]
+ while (NOERROR == lpe->lpVtbl->Next(
+ lpe,
+ 1,
+ &pidlEntry,
+ NULL))
+
+ {
+
+ // Add item to the List if it is part of the
+ // Filesystem
+ dwAttributes = SFGAO_FILESYSTEM;
+
+ lpsf->lpVtbl->GetAttributesOf(
+ lpsf,
+ 1,
+ &pidlEntry,
+ &dwAttributes);
+
+ if (dwAttributes & SFGAO_FILESYSTEM)
+ {
+
+ // Windows XP: check if pidlEntry is a drive
+ SHDESCRIPTIONID di;
+ HRESULT hr;
+ hr = SHGetDataFromIDList(lpsf,pidlEntry,SHGDFIL_DESCRIPTIONID,
+ &di,sizeof(SHDESCRIPTIONID));
+ if (hr != NOERROR || (di.dwDescriptionId >= SHDID_COMPUTER_DRIVE35 &&
+ di.dwDescriptionId <= SHDID_COMPUTER_OTHER))
+ {
+
+ lpdcid = g_lpMalloc->lpVtbl->Alloc(
+ g_lpMalloc,
+ sizeof(DC_ITEMDATA));
+
+ //lpdcid->pidl = IL_Copy(lpMalloc,pidlEntry);
+ lpdcid->pidl = pidlEntry;
+ lpdcid->lpsf = lpsf;
+
+ lpsf->lpVtbl->AddRef(lpsf);
+
+ // Insert sorted ...
+ {
+ COMBOBOXEXITEM cbei2;
+ LPDC_ITEMDATA lpdcid2;
+ HRESULT hr;
+ cbei2.mask = CBEIF_LPARAM;
+ cbei2.iItem = 0;
+
+ while ((SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei2)))
+ {
+ lpdcid2 = (LPDC_ITEMDATA)cbei2.lParam;
+ hr = (lpdcid->lpsf->lpVtbl->CompareIDs(
+ lpdcid->lpsf,
+ 0,
+ lpdcid->pidl,
+ lpdcid2->pidl));
+
+ if ((short)(SCODE_CODE(GetScode(hr))) < 0)
+ break;
+ else
+ cbei2.iItem++;
+ }
+
+ cbei.iItem = cbei2.iItem;
+ cbei.lParam = (LPARAM)lpdcid;
+ SendMessage(hwnd,CBEM_INSERTITEM,0,(LPARAM)&cbei);
+
+ }
+
+ }
+
+ }
+
+ //lpMalloc->lpVtbl->Free(lpMalloc,pidlEntry);
+
+ } // IEnumIDList::Next()
+
+ lpe->lpVtbl->Release(lpe);
+
+ } // IShellFolder::EnumObjects()
+
+ lpsf->lpVtbl->Release(lpsf);
+
+ } // IShellFolder::BindToObject()
+
+ g_lpMalloc->lpVtbl->Free(g_lpMalloc,pidl);
+
+ } // SHGetSpecialFolderLocation()
+
+ lpsfDesktop->lpVtbl->Release(lpsfDesktop);
+
+ } // SHGetDesktopFolder()
+
+ //lpMalloc->lpVtbl->Release(lpMalloc);
+
+ //} // SHGetMalloc()
+
+
+ SendMessage(hwnd,WM_SETREDRAW,1,0);
+ // Return number of items added to combo box
+ return (SendMessage(hwnd,CB_GETCOUNT,0,0));
+
+}
+
+
+//=============================================================================
+//
+// DriveBox_GetSelDrive
+//
+BOOL DriveBox_GetSelDrive(HWND hwnd,LPWSTR lpszDrive,int nDrive,BOOL fNoSlash)
+{
+
+ COMBOBOXEXITEM cbei;
+ LPDC_ITEMDATA lpdcid;
+ int i = SendMessage(hwnd,CB_GETCURSEL,0,0);
+
+ // CB_ERR means no Selection
+ if (i == CB_ERR)
+ return FALSE;
+
+ // Get DC_ITEMDATA* of selected Item
+ cbei.mask = CBEIF_LPARAM;
+ cbei.iItem = i;
+ SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
+ lpdcid = (LPDC_ITEMDATA)cbei.lParam;
+
+ // Get File System Path for Drive
+ IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,lpszDrive,nDrive);
+
+ // Remove Backslash if required (makes Drive relative!!!)
+ if (fNoSlash)
+ PathRemoveBackslash(lpszDrive);
+
+ return TRUE;
+
+}
+
+
+//=============================================================================
+//
+// DriveBox_SelectDrive
+//
+BOOL DriveBox_SelectDrive(HWND hwnd,LPCWSTR lpszPath)
+{
+
+ COMBOBOXEXITEM cbei;
+ LPDC_ITEMDATA lpdcid;
+ WCHAR szRoot[64];
+
+ int i;
+ int cbItems = SendMessage(hwnd,CB_GETCOUNT,0,0);
+
+ // No Drives in Combo Box
+ if (!cbItems)
+ return FALSE;
+
+ cbei.mask = CBEIF_LPARAM;
+
+ for (i = 0; i < cbItems; i++)
+ {
+ // Get DC_ITEMDATA* of Item i
+ cbei.iItem = i;
+ SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
+ lpdcid = (LPDC_ITEMDATA)cbei.lParam;
+
+ // Get File System Path for Drive
+ IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,szRoot,64);
+
+ // Compare Root Directory with Path
+ if (PathIsSameRoot(lpszPath,szRoot))
+ {
+ // Select matching Drive
+ SendMessage(hwnd,CB_SETCURSEL,i,0);
+ return TRUE;
+ }
+ }
+
+ // Don't select anything
+ SendMessage(hwnd,CB_SETCURSEL,(WPARAM)-1,0);
+ return FALSE;
+
+}
+
+
+//=============================================================================
+//
+// DriveBox_PropertyDlg()
+//
+// Shows standard Win95 Property Dlg for selected Drive
+//
+BOOL DriveBox_PropertyDlg(HWND hwnd)
+{
+
+ COMBOBOXEXITEM cbei;
+ LPDC_ITEMDATA lpdcid;
+ int iItem;
+ LPCONTEXTMENU lpcm;
+ CMINVOKECOMMANDINFO cmi;
+ BOOL bSuccess = TRUE;
+
+ static const char *lpVerb = "properties";
+
+ iItem = SendMessage(hwnd,CB_GETCURSEL,0,0);
+
+ if (iItem == CB_ERR)
+ return FALSE;
+
+ cbei.mask = CBEIF_LPARAM;
+ cbei.iItem = iItem;
+ SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
+ lpdcid = (LPDC_ITEMDATA)cbei.lParam;
+
+ if (NOERROR == lpdcid->lpsf->lpVtbl->GetUIObjectOf(
+ lpdcid->lpsf,
+ GetParent(hwnd), // Owner
+ 1, // Number of objects
+ &lpdcid->pidl, // pidl
+ &IID_IContextMenu,
+ NULL,
+ &lpcm))
+ {
+
+ cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
+ cmi.fMask = 0;
+ cmi.hwnd = GetParent(hwnd);
+ cmi.lpVerb = lpVerb;
+ cmi.lpParameters = NULL;
+ cmi.lpDirectory = NULL;
+ cmi.nShow = SW_SHOWNORMAL;
+ cmi.dwHotKey = 0;
+ cmi.hIcon = NULL;
+
+ if (NOERROR != lpcm->lpVtbl->InvokeCommand(lpcm,&cmi))
+ bSuccess = FALSE;
+
+ lpcm->lpVtbl->Release(lpcm);
+
+ }
+
+ else
+ bSuccess = FALSE;
+
+ return(bSuccess);
+
+}
+
+
+//=============================================================================
+//
+// DriveBox_DeleteItem
+//
+LRESULT DriveBox_DeleteItem(HWND hwnd,LPARAM lParam)
+{
+
+ //LPMALLOC lpMalloc;
+ NMCOMBOBOXEX *lpnmcbe;
+ COMBOBOXEXITEM cbei;
+ LPDC_ITEMDATA lpdcid;
+
+ lpnmcbe = (LPVOID)lParam;
+ cbei.iItem = lpnmcbe->ceItem.iItem;
+
+ cbei.mask = CBEIF_LPARAM;
+ SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
+ lpdcid = (LPDC_ITEMDATA)cbei.lParam;
+
+ //SHGetMalloc(&lpMalloc);
+
+ // Free pidl
+ g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdcid->pidl);
+ // Release lpsf
+ lpdcid->lpsf->lpVtbl->Release(lpdcid->lpsf);
+
+ // Free lpdcid itself
+ g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdcid);
+
+ // Release lpMalloc
+ //lpMalloc->lpVtbl->Release(lpMalloc);
+
+ return TRUE;
+
+}
+
+
+//=============================================================================
+//
+// DriveBox_GetDispInfo
+//
+LRESULT DriveBox_GetDispInfo(HWND hwnd,LPARAM lParam)
+{
+
+ NMCOMBOBOXEX *lpnmcbe;
+ LPDC_ITEMDATA lpdcid;
+ SHFILEINFO shfi;
+ WCHAR szTemp[256];
+
+ lpnmcbe = (LPVOID)lParam;
+ lpdcid = (LPDC_ITEMDATA)lpnmcbe->ceItem.lParam;
+
+ if (!lpdcid)
+ return FALSE;
+
+ // Get Display Name
+ if (lpnmcbe->ceItem.mask & CBEIF_TEXT)
+ IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_NORMAL,lpnmcbe->ceItem.pszText,lpnmcbe->ceItem.cchTextMax);
+
+ // Get Icon Index
+ if (lpnmcbe->ceItem.mask & (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE))
+ {
+ IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,szTemp,256);
+ SHGetFileInfo(szTemp,0,&shfi,sizeof(SHFILEINFO),SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
+ lpnmcbe->ceItem.iImage = shfi.iIcon;
+ lpnmcbe->ceItem.iSelectedImage = shfi.iIcon;
+ }
+
+ // Set values
+ lpnmcbe->ceItem.mask |= CBEIF_DI_SETITEM;
+
+ return TRUE;
+
+}
+
+
+
+//==== ItemID =================================================================
+
+//=============================================================================
+//
+// IL_Create()
+//
+// Creates an ITEMIDLIST by concatenating pidl1 and pidl2
+// cb1 and cb2 indicate the sizes of the pidls, where cb1
+// can be zero and pidl1 can be NULL
+//
+// If cb2 is zero, the size of pidl2 is retrieved using
+// IL_GetSize(pidl2)
+//
+LPITEMIDLIST IL_Create(LPMALLOC lpMalloc,
+ LPCITEMIDLIST pidl1,UINT cb1,
+ LPCITEMIDLIST pidl2,UINT cb2)
+{
+
+ LPITEMIDLIST pidl;
+
+ if (!pidl2)
+ return NULL;
+
+ if (!cb2)
+ cb2 = IL_GetSize(pidl2) + 2; // Space for terminating Bytes
+
+ if (!cb1)
+ cb1 = IL_GetSize(pidl1);
+
+ // Allocate Memory
+ pidl = lpMalloc->lpVtbl->Alloc(lpMalloc,cb1 + cb2);
+
+ // Init new ITEMIDLIST
+ if (pidl1)
+ CopyMemory(pidl,pidl1,cb1);
+
+ // pidl2 can't be NULL here
+ CopyMemory((LPBYTE)pidl + cb1,pidl2,cb2);
+
+ return pidl;
+
+}
+
+
+//=============================================================================
+//
+// IL_GetSize()
+//
+// Retrieves the number of bytes in a pidl
+// Does not add space for zero terminators !!
+//
+UINT IL_GetSize(LPCITEMIDLIST pidl)
+{
+
+ LPITEMIDLIST pidlTmp;
+ UINT cb = 0;
+
+ if (!pidl)
+ return 0;
+
+ for (pidlTmp = (LPITEMIDLIST)pidl;
+ pidlTmp->mkid.cb;
+ pidlTmp = _IL_Next(pidlTmp))
+
+ cb += pidlTmp->mkid.cb;
+
+
+ return cb;
+
+}
+
+
+//=============================================================================
+//
+// IL_GetDisplayName()
+//
+// Gets the Display Name of a pidl. lpsf is the parent IShellFolder Interface
+// dwFlags specify a SHGDN_xx value
+//
+BOOL IL_GetDisplayName(LPSHELLFOLDER lpsf,
+ LPCITEMIDLIST pidl,
+ DWORD dwFlags,
+ LPWSTR lpszDisplayName,
+ int nDisplayName)
+{
+
+ STRRET str;
+
+ if (NOERROR == lpsf->lpVtbl->GetDisplayNameOf(lpsf,
+ pidl,
+ dwFlags,
+ &str))
+ {
+
+ // Shlwapi.dll provides new function:
+ return StrRetToBuf(&str,pidl,lpszDisplayName,nDisplayName);
+ // ...but I suppose my version is faster ;-)
+ /*switch (str.uType)
+ {
+
+ case STRRET_WSTR:
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ str.pOleStr,
+ -1,
+ lpszDisplayName,
+ nDisplayName,
+ NULL,
+ NULL);
+ g_lpMalloc->lpVtbl->Free(g_lpMalloc,str.pOleStr);
+ break;
+
+ case STRRET_OFFSET:
+ lstrcpyn(lpszDisplayName,
+ ((WCHAR *)(pidl)) + str.uOffset,
+ nDisplayName);
+ break;
+
+ case STRRET_CSTR:
+ lstrcpyn(lpszDisplayName,str.cStr,nDisplayName);
+ break;
+
+ }
+
+ return TRUE;*/
+ }
+
+ return FALSE;
+}
+
+
+
+/// End of Dlapi.c \\\
|