Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
bitbcksf.c
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 97k
Category:
Windows Kernel
Development Platform:
Visual C++
- #include "shellprv.h"
- #pragma hdrstop
- #include "bitbuck.h"
- #include "fstreex.h"
- #include "util.h"
- #include "copy.h"
- #include "mrsw.h"
- #include "prop.h" // for COL_DATA
- #include "datautil.h"
- STDAPI_(LPITEMIDLIST) ILResize(LPITEMIDLIST pidl, UINT cbRequired, UINT cbExtra);
- // mulprsht.c
- void SetDateTimeText(HWND hdlg, int id, const FILETIME *pftUTC);
- // defext.c
- STDMETHODIMP CCommonShellPropSheetExt_ReplacePage(IShellPropSheetExt * pspx, UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam);
- // fstreex.c
- int FS_CreateMoveCopyList(IDataObject *pdtobj, void *hNameMappings, LPITEMIDLIST **pppidl);
- void FS_PositionItems(HWND hwndOwner, UINT cidl, const LPITEMIDLIST *ppidl, IDataObject *pdtobj, POINT *pptOrigin, BOOL fMove);
- void FS_FreeMoveCopyList(LPITEMIDLIST *ppidl, UINT cidl);
- HRESULT CFSIDLData_QueryGetData(IDataObject * pdtobj, FORMATETC * pformatetc); // subclass member function to support CF_HDROP and CF_NETRESOURCE
- //
- // Prototypes
- //
- void BBGetDisplayName(LPCIDFOLDER pidf, LPTSTR pszPath);
- void BBGetItemPath(LPCIDFOLDER pidf, LPTSTR pszPath);
- STDMETHODIMP CBitBucket_PS_AddPages(IShellPropSheetExt * pspx, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
- LPITEMIDLIST DeletedFilePathToBBPidl(LPTSTR lpszPath);
- //
- // structs
- //
- typedef struct _bbpropsheetinfo
- {
- PROPSHEETPAGE psp;
- int idDrive;
- BOOL fNukeOnDelete;
- BOOL fOriginalNukeOnDelete;
- int iPercent;
- int iOriginalPercent;
- // the following two fields are valid only for the "global" tab, where they represent the state
- // of the "Configure drives independently" / "Use one setting for all drives" checkbox
- BOOL fUseGlobalSettings;
- BOOL fOriginalUseGlobalSettings;
- // this is a pointer to the global property sheet page after it has been copied somewhere by the
- // CreatePropertySheetPage(), we use this to get to the global state of the % slider and fNukeOnDelete
- // from the other tabs
- struct _bbpropsheetinfo* pGlobal;
- } BBPROPSHEETINFO, *LPBBPROPSHEETINFO;
- const static DWORD aBitBucketPropHelpIDs[] = { // Context Help IDs
- IDD_ATTR_GROUPBOX, IDH_COMM_GROUPBOX,
- IDC_INDEPENDENT, IDH_RECYCLE_CONFIG_INDEP,
- IDC_GLOBAL, IDH_RECYCLE_CONFIG_ALL,
- IDC_DISKSIZE, IDH_RECYCLE_DRIVE_SIZE,
- IDC_DISKSIZEDATA, IDH_RECYCLE_DRIVE_SIZE,
- IDC_BYTESIZE, IDH_RECYCLE_BIN_SIZE,
- IDC_BYTESIZEDATA, IDH_RECYCLE_BIN_SIZE,
- IDC_NUKEONDELETE, IDH_RECYCLE_PURGE_ON_DEL,
- IDC_BBSIZE, IDH_RECYCLE_MAX_SIZE,
- IDC_BBSIZETEXT, IDH_RECYCLE_MAX_SIZE,
- IDC_CONFIRMDELETE, IDH_DELETE_CONFIRM_DLG,
- IDC_TEXT, NO_HELP,
- 0, 0
- };
- const static DWORD aBitBucketHelpIDs[] = { // Context Help IDs
- IDD_LINE_1, NO_HELP,
- IDD_LINE_2, NO_HELP,
- IDD_ITEMICON, IDH_FPROP_GEN_ICON,
- IDD_NAME, IDH_FPROP_GEN_NAME,
- IDD_FILETYPE_TXT, IDH_FPROP_GEN_TYPE,
- IDD_FILETYPE, IDH_FPROP_GEN_TYPE,
- IDD_FILESIZE_TXT, IDH_FPROP_GEN_SIZE,
- IDD_FILESIZE, IDH_FPROP_GEN_SIZE,
- IDD_LOCATION_TXT, IDH_FCAB_DELFILEPROP_LOCATION,
- IDD_LOCATION, IDH_FCAB_DELFILEPROP_LOCATION,
- IDD_DELETED_TXT, IDH_FCAB_DELFILEPROP_DELETED,
- IDD_DELETED, IDH_FCAB_DELFILEPROP_DELETED,
- IDD_CREATED_TXT, IDH_FPROP_GEN_DATE_CREATED,
- IDD_CREATED, IDH_FPROP_GEN_DATE_CREATED,
- IDD_READONLY, IDH_FCAB_DELFILEPROP_READONLY,
- IDD_HIDDEN, IDH_FCAB_DELFILEPROP_HIDDEN,
- IDD_ARCHIVE, IDH_FCAB_DELFILEPROP_ARCHIVE,
- IDD_ATTR_GROUPBOX, IDH_COMM_GROUPBOX,
- 0, 0
- };
- //
- // for the pidls
- //
- enum
- {
- ICOL_NAME = 0,
- ICOL_ORIGINAL,
- ICOL_MODIFIED,
- ICOL_TYPE,
- ICOL_SIZE,
- };
- const COL_DATA c_bb_cols[] = {
- {ICOL_NAME, IDS_NAME_COL, 20, LVCFMT_LEFT, &SCID_NAME},
- {ICOL_ORIGINAL, IDS_DELETEDFROM_COL, 20, LVCFMT_LEFT, &SCID_ORIGINALLOCATION},
- {ICOL_MODIFIED, IDS_DATEDELETED_COL, 18, LVCFMT_LEFT, &SCID_DATEDELETED},
- {ICOL_TYPE, IDS_TYPE_COL, 20, LVCFMT_LEFT, &SCID_TYPE},
- {ICOL_SIZE, IDS_SIZE_COL, 8, LVCFMT_RIGHT, &SCID_SIZE}
- };
- //========================================================================
- // CBitBucket members
- //========================================================================
- STDMETHODIMP CBitBucket_SF_QueryInterface(IShellFolder2 *psf, REFIID riid, void **ppvObj)
- {
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- if (IsEqualIID(riid, &IID_IShellFolder) ||
- IsEqualIID(riid, &IID_IShellFolder2) ||
- IsEqualIID(riid, &IID_IUnknown))
- {
- *ppvObj = &this->isf;
- }
- else if (IsEqualIID(riid, &IID_IPersistFolder) ||
- IsEqualIID(riid, &IID_IPersistFolder2) ||
- IsEqualIID(riid, &IID_IPersist))
- {
- *ppvObj = &this->ipf;
- }
- else if (IsEqualIID(riid, &IID_IContextMenu) )
- {
- *ppvObj = &this->icm;
- }
- else if (IsEqualIID(riid, &IID_IShellPropSheetExt))
- {
- *ppvObj = &this->ips;
- }
- else if (IsEqualIID(riid, &IID_IShellExtInit))
- {
- *ppvObj = &this->isei;
- }
- else
- {
- *ppvObj = NULL;
- return E_NOINTERFACE;
- }
- this->cRef++;
- return NOERROR;
- }
- STDMETHODIMP_(ULONG) CBitBucket_SF_Release(IShellFolder2 *psf)
- {
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- if (InterlockedDecrement(&this->cRef))
- return this->cRef;
- ILFree(this->pidl);
- LocalFree((HLOCAL)this);
- return 0;
- }
- STDMETHODIMP_(ULONG) CBitBucket_SF_AddRef(IShellFolder2 *psf)
- {
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- return InterlockedIncrement(&this->cRef);
- }
- BOOL BBGetOriginalPath(LPBBDATAENTRYIDA pbbidl, TCHAR *pszOrig, UINT cch)
- {
- #ifdef UNICODE
- if (pbbidl->cb == SIZEOF(BBDATAENTRYIDW))
- {
- LPBBDATAENTRYIDW pbbidlw = DATAENTRYIDATOW(pbbidl);
- ualstrcpyn(pszOrig, pbbidlw->wszOriginal, cch);
- return (BOOL)*pszOrig;
- }
- #endif
- SHAnsiToTChar(pbbidl->bbde.szOriginal, pszOrig, cch);
- return (BOOL)*pszOrig;
- }
- //
- // We need to be able to compare the names of two bbpidls. Since either of
- // them could be a unicode name, we might have to convert both to unicode.
- //
- int _BBCompareOriginal(LPBBDATAENTRYIDA lpbbidl1, LPBBDATAENTRYIDA lpbbidl2 )
- {
- TCHAR szOrig1[MAX_PATH];
- TCHAR szOrig2[MAX_PATH];
- BBGetOriginalPath(lpbbidl1, szOrig1, ARRAYSIZE(szOrig1));
- BBGetOriginalPath(lpbbidl2, szOrig2, ARRAYSIZE(szOrig2));
- PathRemoveFileSpec(szOrig1);
- PathRemoveFileSpec(szOrig2);
- return lstrcmpi(szOrig1,szOrig2);
- }
- STDMETHODIMP CBitBucket_SF_CompareIDs(IShellFolder2 *psf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
- {
- HRESULT hres = ResultFromShort(-1);
- LPBBDATAENTRYIDA pbbidl1, pbbidl2;
- LPCIDFOLDER pidf1 = FS_IsValidID(pidl1);
- LPCIDFOLDER pidf2 = FS_IsValidID(pidl2);
- short nCmp;
- if (!pidf1 || !pidf2)
- {
- ASSERT(0);
- return E_INVALIDARG;
- }
- pbbidl1 = PIDLTODATAENTRYID(pidl1);
- pbbidl2 = PIDLTODATAENTRYID(pidl2);
- // don't worry about recursing down because we don't have children.
- switch (lParam)
- {
- case ICOL_TYPE:
- nCmp = _CompareFileTypes((IShellFolder *)psf, pidf1, pidf2);
- if (nCmp)
- {
- return ResultFromShort(nCmp);
- }
- else
- {
- goto CompareNames;
- }
- break;
- case ICOL_SIZE:
- {
- ULONGLONG qw1, qw2;
- // BUGBUG (reinerf) - directories are not dealt with properly
- // when sorting by size.
- FS_GetSize(NULL, pidf1, &qw1);
- FS_GetSize(NULL, pidf2, &qw2);
- if (qw1 < qw2)
- {
- return ResultFromShort(-1);
- }
- if (qw1 > qw2)
- {
- return ResultFromShort(1);
- }
- } // else fall through
- CompareNames:
- case ICOL_NAME:
- hres = FS_CompareNamesCase(pidf1, pidf2);
- // compare the real filenames first, if they are different,
- // try comparing the display name
- if ((hres != ResultFromShort(0)) && (BB_IsRealID(pidl1) && BB_IsRealID(pidl2)))
- {
- HRESULT hresOld = hres;
- TCHAR szName1[MAX_PATH], szName2[MAX_PATH];
- BBGetDisplayName(pidf1, szName1);
- BBGetDisplayName(pidf2, szName2);
- hres = ResultFromShort(lstrcmpi(szName1, szName2));
- // if they are from the same location, sort them by delete times
- if (hres == ResultFromShort(0))
- {
- // if the items are same in title, sort by drive
- hres = ResultFromShort(pbbidl1->bbde.idDrive - pbbidl2->bbde.idDrive);
- if (hres == ResultFromShort(0))
- {
- // if the items are still the same, sort by index
- hres = ResultFromShort(pbbidl1->bbde.iIndex - pbbidl2->bbde.iIndex);
- // once we're not equal, we can never be equal again
- ASSERT(hres != ResultFromShort(0));
- if (hres == ResultFromShort(0))
- {
- hres = hresOld;
- }
- }
- }
- }
- break;
- case ICOL_ORIGINAL:
- hres = ResultFromShort(_BBCompareOriginal(pbbidl1, pbbidl2));
- break;
- case ICOL_MODIFIED:
- if (pbbidl1->bbde.ft.dwHighDateTime < pbbidl2->bbde.ft.dwHighDateTime)
- {
- hres = ResultFromShort(-1);
- }
- else if (pbbidl1->bbde.ft.dwHighDateTime > pbbidl2->bbde.ft.dwHighDateTime)
- {
- hres = ResultFromShort(1);
- }
- else
- {
- if (pbbidl1->bbde.ft.dwLowDateTime < pbbidl2->bbde.ft.dwLowDateTime)
- {
- hres = ResultFromShort(-1);
- }
- else if (pbbidl1->bbde.ft.dwLowDateTime > pbbidl2->bbde.ft.dwLowDateTime)
- {
- hres = ResultFromShort(1);
- }
- else
- {
- return 0;
- }
- }
- break;
- }
- return hres;
- }
- STDMETHODIMP CBitBucket_SF_GetAttributesOf(IShellFolder2 *psf, UINT cidl, LPCITEMIDLIST * apidl, ULONG * rgfOut)
- {
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- ULONG gfOut = *rgfOut;
- // asking about the root itself
- if (cidl == 0)
- {
- gfOut = SFGAO_HASPROPSHEET;
- }
- else
- {
- LPCIDFOLDER pidf = FS_IsValidID(apidl[0]);
- gfOut &= (SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM);
- if (*rgfOut & SFGAO_LINK)
- {
- if (SHGetClassFlags(pidf) & SHCF_IS_LINK)
- {
- gfOut |= SFGAO_LINK;
- }
- }
- }
- *rgfOut = gfOut;
- return NOERROR;
- }
- int DataObjToFileOpString(IDataObject * pdtobj, LPTSTR * ppszSrc, LPTSTR * ppszDest)
- {
- int cItems = 0;
- STGMEDIUM medium;
- LPIDA pida = DataObj_GetHIDA(pdtobj, &medium);
- if (pida)
- {
- LPTSTR lpszSrc, lpszDest;
- int i, cchSrc, cchDest;
- cItems = pida->cidl;
- // start with null terminated strings
- cchSrc = cchDest = 1;
- if (ppszSrc)
- lpszSrc = (void*)LocalAlloc(LPTR, cchSrc * SIZEOF(TCHAR));
- if (ppszDest)
- lpszDest = (void*)LocalAlloc(LPTR, cchDest * SIZEOF(TCHAR));
- for (i = 0 ; i < cItems ; i++)
- {
- LPCITEMIDLIST pidl = IDA_GetIDListPtr(pida, i);
- LPBBDATAENTRYIDA pbbidl = PIDLTODATAENTRYID(pidl);
- if (ppszSrc)
- {
- TCHAR szSrc[MAX_PATH];
- int cchSrcFile;
- LPTSTR psz;
- BBGetItemPath((LPIDFOLDER)pidl, szSrc);
- cchSrcFile = lstrlen(szSrc) + 1;
- psz = (LPTSTR)LocalReAlloc((HLOCAL)lpszSrc, (cchSrc + cchSrcFile) * SIZEOF(TCHAR), LMEM_MOVEABLE | LMEM_ZEROINIT);
- if (!psz)
- {
- // out of memory!
- // bugbug: do something real
- LocalFree((HLOCAL)lpszSrc);
- if (ppszDest)
- LocalFree((HLOCAL)lpszDest);
- cItems = 0;
- goto Bail;
- }
- lpszSrc = psz;
- lstrcpy(lpszSrc + cchSrc - 1, szSrc);
- cchSrc += cchSrcFile;
- }
- if (ppszDest)
- {
- TCHAR szOrig[MAX_PATH];
- int cchDestFile;
- LPTSTR psz;
- BBGetOriginalPath(pbbidl, szOrig, ARRAYSIZE(szOrig));
- cchDestFile = lstrlen(szOrig) + 1;
- psz = (LPTSTR)LocalReAlloc((HLOCAL)lpszDest, (cchDest + cchDestFile) * SIZEOF(TCHAR), LMEM_MOVEABLE | LMEM_ZEROINIT);
- if (!psz)
- {
- // out of memory!
- LocalFree((HLOCAL)lpszDest);
- if (ppszSrc)
- LocalFree((HLOCAL)lpszSrc);
- cItems = 0;
- goto Bail;
- }
- lpszDest = psz;
- lstrcpy(lpszDest + cchDest - 1, szOrig);
- cchDest += cchDestFile;
- }
- }
- if (ppszSrc)
- *ppszSrc = lpszSrc;
- if (ppszDest)
- *ppszDest = lpszDest;
- Bail:
- HIDA_ReleaseStgMedium(pida, &medium);
- }
- return cItems;
- }
- //
- // restores the list of files in the IDataObject
- //
- void BBRestoreFileList(CBitBucket *this, HWND hwndOwner, IDataObject * pdtobj)
- {
- LPTSTR pszSrc, pszDest;
- if (DataObjToFileOpString(pdtobj, &pszSrc, &pszDest))
- {
- // now do the actual restore.
- SHFILEOPSTRUCT sFileOp = {hwndOwner,
- FO_MOVE,
- pszSrc,
- pszDest,
- FOF_MULTIDESTFILES | FOF_SIMPLEPROGRESS | FOF_NOCONFIRMMKDIR,
- FALSE,
- NULL,
- MAKEINTRESOURCE(IDS_BB_RESTORINGFILES)};
- DECLAREWAITCURSOR;
- SetWaitCursor();
- if (SHFileOperation(&sFileOp) == ERROR_SUCCESS)
- {
- // success!;
- SHChangeNotifyHandleEvents();
- BBCheckRestoredFiles(pszSrc);
- }
- LocalFree((HLOCAL)pszSrc);
- LocalFree((HLOCAL)pszDest);
- ResetWaitCursor();
- }
- }
- //
- // nukes the list of files in the IDataObject
- //
- void BBNukeFileList(CBitBucket *this, HWND hwndOwner, IDataObject * pdtobj)
- {
- LPTSTR lpszSrc, lpszDest;
- int nFiles = DataObjToFileOpString(pdtobj, &lpszSrc, &lpszDest);
- if (nFiles)
- {
- // now do the actual nuke.
- int iItems;
- WIN32_FIND_DATA fd;
- CONFIRM_DATA cd = {CONFIRM_DELETE_FILE | CONFIRM_DELETE_FOLDER | CONFIRM_PROGRAM_FILE | CONFIRM_MULTIPLE, 0};
- SHFILEOPSTRUCT sFileOp ={hwndOwner,
- FO_DELETE,
- lpszSrc,
- NULL,
- FOF_NOCONFIRMATION | FOF_SIMPLEPROGRESS,
- FALSE,
- NULL,
- MAKEINTRESOURCE(IDS_BB_DELETINGWASTEBASKETFILES)};
- DECLAREWAITCURSOR;
- SetWaitCursor();
- fd.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
- if (ConfirmFileOp(hwndOwner, NULL, &cd, nFiles, 0, CONFIRM_DELETE_FILE | CONFIRM_WASTEBASKET_PURGE, lpszDest, &fd, NULL, &fd, NULL) == IDYES)
- {
- SHFileOperation(&sFileOp);
- SHChangeNotifyHandleEvents();
- // update the icon if there are objects left in the list
- iItems = (int) ShellFolderView_GetObjectCount(hwndOwner);
- UpdateIcon(iItems);
- }
- LocalFree((HLOCAL)lpszSrc);
- LocalFree((HLOCAL)lpszDest);
- ResetWaitCursor();
- }
- }
- void EnableTrackbarAndFamily(HWND hDlg, BOOL f)
- {
- EnableWindow(GetDlgItem(hDlg, IDC_BBSIZE), f);
- EnableWindow(GetDlgItem(hDlg, IDC_BBSIZETEXT), f);
- EnableWindow(GetDlgItem(hDlg, IDC_TEXT), f);
- }
- void BBGlobalPropOnCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
- {
- LPBBPROPSHEETINFO ppsi = (LPBBPROPSHEETINFO)GetWindowLongPtr(hDlg, DWLP_USER);
- BOOL fNukeOnDelete;
- switch (id)
- {
- case IDC_GLOBAL:
- case IDC_INDEPENDENT:
- fNukeOnDelete = IsDlgButtonChecked(hDlg, IDC_NUKEONDELETE);
- ppsi->fUseGlobalSettings = (IsDlgButtonChecked(hDlg, IDC_GLOBAL) == BST_CHECKED) ? TRUE : FALSE;
- EnableWindow(GetDlgItem(hDlg, IDC_NUKEONDELETE), ppsi->fUseGlobalSettings);
- EnableTrackbarAndFamily(hDlg, ppsi->fUseGlobalSettings && !fNukeOnDelete);
- SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
- break;
- case IDC_NUKEONDELETE:
- fNukeOnDelete = IsDlgButtonChecked(hDlg, IDC_NUKEONDELETE);
- if (fNukeOnDelete)
- {
- // In order to help protect users, when they turn on "Remove files immedately" we also
- // check the "show delete confimation" box automatically for them. Thus, they will have
- // to explicitly uncheck it if they do not want confimation that their files will be nuked.
- CheckDlgButton(hDlg, IDC_CONFIRMDELETE, BST_CHECKED);
- }
- EnableTrackbarAndFamily(hDlg, !fNukeOnDelete);
- // fall through
- case IDC_CONFIRMDELETE:
- SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
- break;
- }
- }
- void RelayMessageToChildren(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
- {
- HWND hwndChild;
- for (hwndChild = GetWindow(hwnd, GW_CHILD); hwndChild != NULL; hwndChild = GetWindow(hwndChild, GW_HWNDNEXT))
- {
- SendMessage(hwndChild, uMessage, wParam, lParam);
- }
- }
- //
- // This is the dlg proc for the "Global" tab on the recycle bin
- //
- BOOL_PTR CALLBACK BBGlobalPropDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- LPBBPROPSHEETINFO ppsi = (LPBBPROPSHEETINFO)GetWindowLongPtr(hDlg, DWLP_USER);
- switch (uMsg)
- {
- HANDLE_MSG(hDlg, WM_COMMAND, BBGlobalPropOnCommand);
- case WM_INITDIALOG:
- {
- HWND hwndTrack = GetDlgItem(hDlg, IDC_BBSIZE);
- SHELLSTATE ss;
- // make sure the info we have is current
- RefreshAllBBDriveSettings();
- ppsi = (LPBBPROPSHEETINFO)lParam;
- SetWindowLongPtr(hDlg, DWLP_USER, lParam);
- SendMessage(hwndTrack, TBM_SETTICFREQ, 10, 0);
- SendMessage(hwndTrack, TBM_SETRANGE, FALSE, MAKELONG(0, 100));
- SendMessage(hwndTrack, TBM_SETPOS, TRUE, ppsi->iOriginalPercent);
- EnableWindow(GetDlgItem(hDlg, IDC_NUKEONDELETE), ppsi->fUseGlobalSettings);
- EnableTrackbarAndFamily(hDlg, ppsi->fUseGlobalSettings && !ppsi->fNukeOnDelete);
- CheckDlgButton(hDlg, IDC_NUKEONDELETE, ppsi->fNukeOnDelete);
- CheckRadioButton(hDlg, IDC_INDEPENDENT, IDC_GLOBAL, ppsi->fUseGlobalSettings ? IDC_GLOBAL : IDC_INDEPENDENT);
- SHGetSetSettings(&ss, SSF_NOCONFIRMRECYCLE, FALSE);
- CheckDlgButton(hDlg, IDC_CONFIRMDELETE, !ss.fNoConfirmRecycle);
- }
- // fall through to set iGlobalPercent
- case WM_HSCROLL:
- {
- TCHAR szPercent[20];
- HWND hwndTrack = GetDlgItem(hDlg, IDC_BBSIZE);
- ppsi->iPercent = (int) SendMessage(hwndTrack, TBM_GETPOS, 0, 0);
- wsprintf(szPercent, TEXT("%d%%"), ppsi->iPercent);
- SetDlgItemText(hDlg, IDC_BBSIZETEXT, szPercent);
- if (ppsi->iPercent != ppsi->iOriginalPercent)
- {
- SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
- if (ppsi->iPercent == 0)
- {
- // In order to help protect users, when they set the % slider to zero we also
- // check the "show delete confimation" box automatically for them. Thus, they will have
- // to explicitly uncheck it if they do not want confimation that their files will be nuked.
- CheckDlgButton(hDlg, IDC_CONFIRMDELETE, BST_CHECKED);
- }
- }
- return TRUE;
- }
- case WM_HELP:
- WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL,
- HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aBitBucketPropHelpIDs);
- return TRUE;
- case WM_CONTEXTMENU:
- WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU,
- (ULONG_PTR)(LPVOID) aBitBucketPropHelpIDs);
- return TRUE;
- case WM_WININICHANGE:
- case WM_SYSCOLORCHANGE:
- case WM_DISPLAYCHANGE:
- RelayMessageToChildren(hDlg, uMsg, wParam, lParam);
- break;
- case WM_DESTROY:
- CheckCompactAndPurge();
- SHUpdateRecycleBinIcon();
- break;
- case WM_NOTIFY:
- switch (((NMHDR *)lParam)->code)
- {
- case PSN_APPLY:
- {
- SHELLSTATE ss;
- ss.fNoConfirmRecycle = !IsDlgButtonChecked(hDlg, IDC_CONFIRMDELETE);
- SHGetSetSettings(&ss, SSF_NOCONFIRMRECYCLE, TRUE);
- ppsi->fNukeOnDelete = (IsDlgButtonChecked(hDlg, IDC_NUKEONDELETE) == BST_CHECKED) ? TRUE : FALSE;
- ppsi->fUseGlobalSettings = (IsDlgButtonChecked(hDlg, IDC_INDEPENDENT) == BST_CHECKED) ? FALSE : TRUE;
- // if anything on the global tab changed, update all the drives
- if (ppsi->fUseGlobalSettings != ppsi->fOriginalUseGlobalSettings ||
- ppsi->fNukeOnDelete != ppsi->fOriginalNukeOnDelete ||
- ppsi->iPercent != ppsi->iOriginalPercent)
- {
- int i;
- // NOTE: We get a PSN_APPLY after all the drive tabs. This has to be this way so that
- // if global settings change, then the global tab will re-apply all the most current settings
- // bassed on the global variables that get set above.
- // this sets the new global settings in the registry
- if (!PersistGlobalSettings(ppsi->fUseGlobalSettings, ppsi->fNukeOnDelete, ppsi->iPercent))
- {
- // we failed, so show the error dialog and bail
- ShellMessageBox(HINST_THISDLL,
- hDlg,
- MAKEINTRESOURCE(IDS_BB_CANNOTCHANGESETTINGS),
- MAKEINTRESOURCE(IDS_WASTEBASKET),
- MB_OK | MB_ICONEXCLAMATION);
- SetDlgMsgResult(hDlg, WM_NOTIFY, PSNRET_INVALID_NOCHANGEPAGE);
- return TRUE;
- }
- for (i = 0; i < MAX_BITBUCKETS ; i++)
- {
- if (MakeBitBucket(i))
- {
- BOOL bPurge = TRUE;
- // we need to purge all the drives in this case
- RegSetValueEx(g_pBitBucket[i]->hkeyPerUser, TEXT("NeedToPurge"), 0, REG_DWORD, (LPBYTE)&bPurge, SIZEOF(bPurge));
- RefreshBBDriveSettings(i);
- }
- }
- ppsi->fOriginalUseGlobalSettings = ppsi->fUseGlobalSettings;
- ppsi->fOriginalNukeOnDelete = ppsi->fNukeOnDelete;
- ppsi->iOriginalPercent = ppsi->iPercent;
- }
- }
- }
- break;
- SetDlgMsgResult(hDlg, WM_NOTIFY, 0);
- return TRUE;
- }
- return FALSE;
- }
- BOOL_PTR CALLBACK BBDriveDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- LPBBPROPSHEETINFO ppsi = (LPBBPROPSHEETINFO)GetWindowLongPtr(hDlg, DWLP_USER);
- TCHAR szDiskSpace[40];
- HWND hwndTrack;
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- hwndTrack = GetDlgItem(hDlg, IDC_BBSIZE);
- ppsi = (LPBBPROPSHEETINFO)lParam;
- SetWindowLongPtr(hDlg, DWLP_USER, lParam);
- SendMessage(hwndTrack, TBM_SETTICFREQ, 10, 0);
- SendMessage(hwndTrack, TBM_SETRANGE, FALSE, MAKELONG(0, 100));
- SendMessage(hwndTrack, TBM_SETPOS, TRUE, ppsi->iPercent);
- CheckDlgButton(hDlg, IDC_NUKEONDELETE, ppsi->fNukeOnDelete);
- // set the disk space info
- StrFormatByteSize64(g_pBitBucket[ppsi->idDrive]->qwDiskSize, szDiskSpace, ARRAYSIZE(szDiskSpace));
- SetDlgItemText(hDlg, IDC_DISKSIZEDATA, szDiskSpace);
- wParam = 0;
- }
- // fall through
- case WM_HSCROLL:
- {
- ULARGE_INTEGER ulBucketSize;
- HWND hwndTrack = GetDlgItem(hDlg, IDC_BBSIZE);
- ppsi->iPercent = (int)SendMessage(hwndTrack, TBM_GETPOS, 0, 0);
- wsprintf(szDiskSpace, TEXT("%d%%"), ppsi->iPercent);
- SetDlgItemText(hDlg, IDC_BBSIZETEXT, szDiskSpace);
- if (ppsi->iPercent != ppsi->iOriginalPercent)
- {
- SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
- }
- // we peg the max size of the recycle bin to 4 gig
- ulBucketSize.QuadPart = (ppsi->pGlobal->fUseGlobalSettings ? ppsi->pGlobal->iPercent : ppsi->iPercent) * (g_pBitBucket[ppsi->idDrive]->qwDiskSize / 100);
- StrFormatByteSize64(ulBucketSize.HighPart ? (DWORD)-1 : ulBucketSize.LowPart, szDiskSpace, ARRAYSIZE(szDiskSpace));
- SetDlgItemText(hDlg, IDC_BYTESIZEDATA, szDiskSpace);
- return TRUE;
- }
- case WM_HELP:
- WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL,
- HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aBitBucketPropHelpIDs);
- return TRUE;
- case WM_CONTEXTMENU:
- WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU,
- (ULONG_PTR)(LPVOID) aBitBucketPropHelpIDs);
- return TRUE;
- case WM_COMMAND:
- {
- WORD wCommandID = GET_WM_COMMAND_ID(wParam, lParam);
- if (wCommandID == IDC_NUKEONDELETE)
- {
- SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
- EnableTrackbarAndFamily(hDlg, !IsDlgButtonChecked(hDlg, IDC_NUKEONDELETE));
- EnableWindow(GetDlgItem(hDlg, IDC_BYTESIZE), !IsDlgButtonChecked(hDlg, IDC_NUKEONDELETE));
- EnableWindow(GetDlgItem(hDlg, IDC_BYTESIZEDATA), !IsDlgButtonChecked(hDlg, IDC_NUKEONDELETE));
- }
- break;
- }
- case WM_NOTIFY:
- switch (((NMHDR *)lParam)->code)
- {
- case PSN_APPLY:
- {
- ppsi->fNukeOnDelete = (IsDlgButtonChecked(hDlg, IDC_NUKEONDELETE) == BST_CHECKED) ? TRUE : FALSE;
- // update the info in the registry
- if (!PersistBBDriveSettings(ppsi->idDrive, ppsi->iPercent, ppsi->fNukeOnDelete))
- {
- // we failed, so show the error dialog and bail
- ShellMessageBox(HINST_THISDLL,
- hDlg,
- MAKEINTRESOURCE(IDS_BB_CANNOTCHANGESETTINGS),
- MAKEINTRESOURCE(IDS_WASTEBASKET),
- MB_OK | MB_ICONEXCLAMATION);
- SetDlgMsgResult(hDlg, WM_NOTIFY, PSNRET_INVALID_NOCHANGEPAGE);
- return TRUE;
- }
- // only purge this drive if the user set the slider to a smaller value
- if (ppsi->iPercent < ppsi->iOriginalPercent)
- {
- BOOL bPurge = TRUE;
- // since this drive just shrunk, we need to purge the files in it
- RegSetValueEx(g_pBitBucket[ppsi->idDrive]->hkeyPerUser, TEXT("NeedToPurge"), 0, REG_DWORD, (LPBYTE)&bPurge, SIZEOF(bPurge));
- }
- ppsi->iOriginalPercent = ppsi->iPercent;
- ppsi->fOriginalNukeOnDelete = ppsi->fNukeOnDelete;
- // update the g_pBitBucket[] for this drive
- // NOTE: We get a PSN_APPLY before the global tab does. This has to be this way so that
- // if global settings change, then the global tab will re-apply all the most current settings
- // bassed on the global variables that get set in his tab.
- RefreshBBDriveSettings(ppsi->idDrive);
- }
- break;
- case PSN_SETACTIVE:
- {
- BOOL fNukeOnDelete = IsDlgButtonChecked(hDlg, IDC_NUKEONDELETE);
- EnableWindow(GetDlgItem(hDlg, IDC_NUKEONDELETE), !ppsi->pGlobal->fUseGlobalSettings);
- EnableTrackbarAndFamily(hDlg, !ppsi->pGlobal->fUseGlobalSettings && !fNukeOnDelete);
- EnableWindow(GetDlgItem(hDlg, IDC_BYTESIZE), !fNukeOnDelete);
- EnableWindow(GetDlgItem(hDlg, IDC_BYTESIZEDATA), !fNukeOnDelete);
- // send this to make sure that the "space reserved" field is accurate when using global settings
- SendMessage(hDlg, WM_HSCROLL, 0, 0);
- }
- break;
- }
- SetDlgMsgResult(hDlg, WM_NOTIFY, 0);
- return TRUE;
- }
- return FALSE;
- }
- //
- // this is the property sheet page for a file/folder in the bitbucket
- //
- BOOL_PTR CALLBACK BBFilePropDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- BBFILEPROPINFO * pbbfpi = (BBFILEPROPINFO *)GetWindowLongPtr(hDlg, DWLP_USER);
- TCHAR szTemp[MAX_PATH];
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- LPCITEMIDLIST pidl;
- LPBBDATAENTRYIDA pbbidl;
- HICON hIcon;
- ULONGLONG cbSize;
- pbbfpi = (BBFILEPROPINFO *)lParam;
- SetWindowLongPtr(hDlg, DWLP_USER, lParam);
- pidl = pbbfpi->pidl;
- pbbidl = PIDLTODATAENTRYID(pidl);
- BBGetOriginalPath(pbbidl, szTemp, ARRAYSIZE(szTemp));
- #ifdef WINNT
- //
- // We don't allow user to change compression attribute on a deleted file
- // but we do show the current compressed state
- //
- {
- TCHAR szRoot[_MAX_PATH + 1];
- DWORD dwVolumeFlags = 0;
- DWORD dwFileAttributes;
- TCHAR szFSName[12];
- //
- // If file's volume doesn't support compression, don't show
- // "Compressed" checkbox.
- // If compression is supported, show the checkbox and check/uncheck
- // it to indicate compression state of the file.
- // Perform this operation while szTemp contains complete path name.
- //
- lstrcpy(szRoot, szTemp);
- PathQualify(szRoot);
- PathStripToRoot(szRoot);
- dwFileAttributes = GetFileAttributes(szTemp);
- if (GetVolumeInformation(szRoot, NULL, 0, NULL, NULL, &dwVolumeFlags, szFSName, ARRAYSIZE(szFSName)) &&
- (dwFileAttributes != (DWORD)-1))
- {
- if (dwVolumeFlags & FS_FILE_COMPRESSION)
- {
- if (dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)
- {
- CheckDlgButton(hDlg, IDD_COMPRESS, 1);
- }
- ShowWindow(GetDlgItem(hDlg, IDD_COMPRESS), SW_SHOW);
- }
- if (g_bRunOnNT5)
- {
- // BUGBUG (ccteng) - HACK
- // Before NTFS implements FS_FILE_ENCRYPTION, we check the compression
- // flag instead, which works as long as we also check for g_bRunOnNT5.
- // After we switch to FS_FILE_ENCRYPTION,
- // we can also remove if (g_bRunOnNT5).
- // if (dwVolumeFlags & FS_FILE_ENCRYPTION)
- if (dwVolumeFlags & FS_FILE_COMPRESSION)
- {
- if (dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED)
- {
- CheckDlgButton(hDlg, IDD_ENCRYPT, 1);
- }
- ShowWindow(GetDlgItem(hDlg, IDD_ENCRYPT), SW_SHOW);
- }
- }
- }
- }
- #else
- //
- // Win95 doesn't support compression/encryption
- //
- #endif
- PathRemoveExtension(szTemp);
- SetDlgItemText(hDlg, IDD_NAME, PathFindFileName(szTemp));
- // origin
- PathRemoveFileSpec(szTemp);
- SetDlgItemText(hDlg, IDD_LOCATION, PathFindFileName(szTemp));
- // Type
- FS_GetTypeName((LPIDFOLDER)pidl, szTemp, ARRAYSIZE(szTemp));
- SetDlgItemText(hDlg, IDD_FILETYPE, szTemp);
- // Size
- if (FS_IsFolder((LPIDFOLDER)pidl))
- cbSize = pbbidl->bbde.dwSize;
- else
- FS_GetSize(NULL, (LPIDFOLDER)pidl, &cbSize);
- StrFormatByteSize64(cbSize, szTemp, ARRAYSIZE(szTemp));
- SetDlgItemText(hDlg, IDD_FILESIZE, szTemp);
- // deleted time
- {
- FILETIME ft = pbbidl->bbde.ft;
- SetDateTimeText(hDlg, IDD_DELETED, &ft);
- }
- {
- HANDLE hfind;
- WIN32_FIND_DATA fd;
- BBGetItemPath((LPIDFOLDER)pidl, szTemp);
- hfind = FindFirstFile(szTemp, &fd);
- if (hfind != INVALID_HANDLE_VALUE)
- {
- SetDateTimeText(hDlg, IDD_CREATED, &fd.ftCreationTime);
- FindClose(hfind);
- }
- // file attributes
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
- CheckDlgButton(hDlg, IDD_READONLY, 1);
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
- CheckDlgButton(hDlg, IDD_ARCHIVE, 1);
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
- CheckDlgButton(hDlg, IDD_HIDDEN, 1);
- // icon
- hIcon = SHGetFileIcon(NULL, szTemp, fd.dwFileAttributes, SHGFI_LARGEICON|SHGFI_USEFILEATTRIBUTES);
- if (hIcon)
- {
- hIcon = (HICON)SendDlgItemMessage(hDlg, IDD_ITEMICON, STM_SETICON, (WPARAM)hIcon, 0L);
- if (hIcon)
- DestroyIcon(hIcon);
- }
- }
- break;
- }
- case WM_WININICHANGE:
- case WM_SYSCOLORCHANGE:
- case WM_DISPLAYCHANGE:
- RelayMessageToChildren(hDlg, uMsg, wParam, lParam);
- break;
- case WM_NOTIFY:
- switch (((NMHDR *)lParam)->code)
- {
- case PSN_APPLY:
- case PSN_SETACTIVE:
- case PSN_KILLACTIVE:
- return TRUE;
- }
- break;
- case WM_HELP:
- WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL,
- HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aBitBucketHelpIDs);
- return TRUE;
- case WM_CONTEXTMENU:
- WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU,
- (ULONG_PTR)(LPVOID) aBitBucketHelpIDs);
- return TRUE;
- }
- return FALSE;
- }
- void BBGetDriveDisplayName(int idDrive, LPTSTR pszName, UINT cchSize)
- {
- TCHAR szDrive[MAX_PATH];
- SHFILEINFO sfi;
- VDATEINPUTBUF(pszName, TCHAR, cchSize);
- DriveIDToBBRoot(idDrive, szDrive);
- if (SHGetFileInfo(szDrive, 0, &sfi, SIZEOF(sfi), SHGFI_DISPLAYNAME))
- {
- lstrcpyn(pszName, sfi.szDisplayName, cchSize);
- }
- // If SERVERDRIVE, attempt to overwrite the default display name with the display
- // name for the mydocs folder on the desktop, since SERVERDRIVE==mydocs for now
- if (idDrive == SERVERDRIVE)
- {
- GetMyDocumentsDisplayName(pszName, cchSize);
- }
- }
- BOOL CALLBACK _BB_AddPage(HPROPSHEETPAGE psp, LPARAM lParam)
- {
- LPPROPSHEETHEADER ppsh = (LPPROPSHEETHEADER)lParam;
- ppsh->phpage[ppsh->nPages++] = psp;
- return TRUE;
- }
- DWORD CALLBACK _BB_PropertiesThread(IDataObject * pdtobj)
- {
- HPROPSHEETPAGE ahpage[MAXPROPPAGES];
- TCHAR szTitle[80];
- PROPSHEETHEADER psh;
- UNIQUESTUBINFO usi;
- LPITEMIDLIST pidlBitBucket = SHCloneSpecialIDList(NULL, CSIDL_BITBUCKET, FALSE);
- BOOL fUnique;
- psh.dwSize = SIZEOF(psh);
- psh.dwFlags = PSH_PROPTITLE;
- psh.hInstance = HINST_THISDLL;
- // psh.hwndParent = NULL; // will be filled in later
- psh.nStartPage = 0;
- psh.phpage = ahpage;
- psh.nPages = 0;
- if (pdtobj)
- {
- // this is the recycled file properties case,
- // we only show the proeprties for the first file if
- // there is a multiple selection
- BBFILEPROPINFO bbfpi;
- STGMEDIUM medium;
- LPITEMIDLIST pidlSave;
- TCHAR szTemp[MAX_PATH];
- LPBBDATAENTRYIDA lpbbidl;
- LPIDA pida;
- pida = DataObj_GetHIDA(pdtobj, &medium);
- pidlSave = ILCombine(pidlBitBucket, IDA_GetIDListPtr(pida, 0));
- fUnique = EnsureUniqueStub(pidlSave, STUBCLASS_PROPSHEET, NULL, &usi);
- ILFree(pidlSave);
- if (!fUnique) // found other window
- goto Cleanup;
- bbfpi.psp.dwFlags = 0;
- bbfpi.psp.dwSize = SIZEOF(bbfpi);
- bbfpi.psp.hInstance = HINST_THISDLL;
- bbfpi.psp.pszTemplate = MAKEINTRESOURCE(DLG_DELETEDFILEPROP);
- bbfpi.psp.pfnDlgProc = BBFilePropDlgProc;
- bbfpi.psp.pszTitle = szTitle;
- bbfpi.hida = medium.hGlobal;
- bbfpi.pidl = IDA_GetIDListPtr(pida, 0);
- lpbbidl = PIDLTODATAENTRYID(bbfpi.pidl);
- BBGetOriginalPath(lpbbidl, szTemp, ARRAYSIZE(szTemp));
- lstrcpyn(szTitle, PathFindFileName(szTemp), ARRAYSIZE(szTitle));
- PathRemoveExtension(szTitle);
- psh.phpage[0] = CreatePropertySheetPage(&bbfpi.psp);
- HIDA_ReleaseStgMedium(pida, &medium);
- psh.nPages = 1;
- psh.pszCaption = szTitle;
- }
- else
- {
- // this is the recycle bin property sheet case
- fUnique = EnsureUniqueStub(pidlBitBucket, STUBCLASS_PROPSHEET, NULL, &usi);
- if (!fUnique)
- goto Cleanup;
- CBitBucket_PS_AddPages(NULL, _BB_AddPage, (LPARAM)&psh);
- psh.pszCaption = MAKEINTRESOURCE(IDS_WASTEBASKET);
- }
- psh.hwndParent = usi.hwndStub;
- PropertySheet(&psh);
- Cleanup:
- if (pidlBitBucket)
- ILFree(pidlBitBucket);
- FreeUniqueStub(&usi);
- return TRUE;
- }
- typedef struct _bb_threaddata {
- CBitBucket* pbb;
- HWND hwndOwner;
- IDataObject * pdtobj;
- IStream *pstmDataObj;
- ULONG_PTR idCmd;
- POINT ptDrop;
- BOOL fSameHwnd;
- BOOL fDragDrop;
- } BBTHREADDATA;
- DWORD WINAPI BB_DropThreadInit(BBTHREADDATA *pbbtd)
- {
- STGMEDIUM medium;
- FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
- if (SUCCEEDED(pbbtd->pdtobj->lpVtbl->GetData(pbbtd->pdtobj, &fmte, &medium)))
- {
- // call delete here so that files will be moved in
- // their respective bins, not necessarily this one.
- DRAGINFO di;
- di.uSize = SIZEOF(DRAGINFO);
- if (DragQueryInfo(medium.hGlobal, &di))
- {
- // Since BBWillRecycle() can return true even when the file will NOT be
- // recycled (eg the file will be nuked), we want to warn the user when we
- // are going to nuke something that they initiall thought that it would
- // be recycled
- UINT fOptions = SD_WARNONNUKE;
- if (!BBWillRecycle(di.lpFileList, NULL) ||
- (di.lpFileList && (di.lpFileList[lstrlen(di.lpFileList)+1] == 0)
- && PathIsShortcutToProgram(di.lpFileList)))
- fOptions = SD_USERCONFIRMATION;
- if (IsFileInBitBucket(di.lpFileList))
- {
- LPITEMIDLIST *ppidl = NULL;
- int cidl = FS_CreateMoveCopyList(pbbtd->pdtobj, NULL, &ppidl);
- if (ppidl)
- {
- FS_PositionItems(pbbtd->hwndOwner, cidl, ppidl, pbbtd->pdtobj, &pbbtd->ptDrop, pbbtd->fDragDrop);
- FS_FreeMoveCopyList(ppidl, cidl);
- }
- }
- else
- {
- TransferDelete(pbbtd->hwndOwner, medium.hGlobal, fOptions);
- }
- SHChangeNotifyHandleEvents();
- SHFree(di.lpFileList);
- }
- ReleaseStgMedium(&medium);
- }
- return 0;
- }
- DWORD CALLBACK _BB_DispatchThreadProc(void *pv)
- {
- BBTHREADDATA *pbbtd = (BBTHREADDATA *)pv;
- if (pbbtd->pstmDataObj)
- {
- CoGetInterfaceAndReleaseStream(pbbtd->pstmDataObj, &IID_IDataObject, (void **)&pbbtd->pdtobj);
- pbbtd->pstmDataObj = NULL; // this is dead
- }
- switch(pbbtd->idCmd)
- {
- case DFM_CMD_MOVE:
- if (pbbtd->pdtobj)
- BB_DropThreadInit(pbbtd);
- break;
- case DFM_CMD_PROPERTIES:
- case FSIDM_PROPERTIESBG: // NULL pdtobj is valid
- _BB_PropertiesThread(pbbtd->pdtobj);
- break;
- case DFM_CMD_DELETE:
- if (pbbtd->pdtobj)
- BBNukeFileList(pbbtd->pbb, pbbtd->hwndOwner, pbbtd->pdtobj);
- break;
- case FSIDM_RESTORE:
- if (pbbtd->pdtobj)
- BBRestoreFileList(pbbtd->pbb, pbbtd->hwndOwner, pbbtd->pdtobj);
- break;
- }
- if (pbbtd->pdtobj)
- pbbtd->pdtobj->lpVtbl->Release(pbbtd->pdtobj);
- if (pbbtd->pbb)
- pbbtd->pbb->isf.lpVtbl->Release(&pbbtd->pbb->isf);
- LocalFree((HLOCAL)pbbtd);
- return 0;
- }
- HRESULT BB_LaunchThread(CBitBucket *this, HWND hwndOwner, IDataObject * pdtobj, WPARAM idCmd)
- {
- HRESULT hr = E_OUTOFMEMORY;
- BBTHREADDATA *pbbtd = (BBTHREADDATA *)LocalAlloc(LPTR, SIZEOF(*pbbtd));
- if (pbbtd)
- {
- pbbtd->pbb = this;
- pbbtd->hwndOwner = hwndOwner;
- pbbtd->idCmd = idCmd;
- if (idCmd == DFM_CMD_MOVE)
- {
- pbbtd->fDragDrop = (BOOL) ShellFolderView_GetDropPoint(hwndOwner, &pbbtd->ptDrop);
- }
- if (this)
- this->isf.lpVtbl->AddRef(&this->isf);
- if (pdtobj)
- CoMarshalInterThreadInterfaceInStream(&IID_IDataObject, (IUnknown *)pdtobj, &pbbtd->pstmDataObj);
- if (SHCreateThread(_BB_DispatchThreadProc, pbbtd, CTF_COINIT, NULL))
- {
- hr = NOERROR;
- }
- else
- {
- if (pbbtd->pstmDataObj)
- pbbtd->pstmDataObj->lpVtbl->Release(pbbtd->pstmDataObj);
- if (this)
- this->isf.lpVtbl->Release(&this->isf);
- LocalFree((HLOCAL)pbbtd);
- }
- }
- return hr;
- }
- const TCHAR c_szUnDelete[] = TEXT("undelete");
- const TCHAR c_szPurgeAll[] = TEXT("empty");
- HRESULT GetVerb(UINT_PTR idCmd, LPSTR pszName, UINT cchMax, BOOL bUnicode)
- {
- HRESULT hres;
- LPCTSTR pszNameT;
- switch (idCmd)
- {
- case FSIDM_RESTORE:
- pszNameT = c_szUnDelete;
- break;
- case FSIDM_PURGEALL:
- pszNameT = c_szPurgeAll;
- break;
- default:
- return E_NOTIMPL;
- }
- if (bUnicode)
- hres = SHTCharToUnicode(pszNameT, (LPWSTR)pszName, cchMax);
- else
- hres = SHTCharToAnsi(pszNameT, (LPSTR)pszName, cchMax);
- return hres;
- }
- //
- // Callback from DefCM
- //
- HRESULT CALLBACK CBitBucket_DFMCallBack(IShellFolder *psf, HWND hwndOwner,
- IDataObject * pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- HRESULT hres = NOERROR; // assume no error
- switch(uMsg)
- {
- case DFM_MERGECONTEXTMENU:
- CDefFolderMenu_MergeMenu(HINST_THISDLL, POPUP_BITBUCKET_ITEM, 0, (LPQCMINFO)lParam);
- hres = ResultFromShort(-1); // return 1 so default reg commands won't be added
- break;
- case DFM_MAPCOMMANDNAME:
- if (lstrcmpi((LPCTSTR)lParam, c_szUnDelete) == 0)
- {
- *(int *)wParam = FSIDM_RESTORE;
- }
- else
- {
- // command not found
- hres = E_FAIL;
- }
- break;
- case DFM_INVOKECOMMAND:
- switch (wParam)
- {
- case FSIDM_RESTORE:
- case DFM_CMD_DELETE:
- case DFM_CMD_PROPERTIES:
- hres = BB_LaunchThread(this, hwndOwner, pdtobj, wParam);
- break;
- default:
- hres = S_FALSE;
- break;
- }
- break;
- case DFM_GETHELPTEXT:
- LoadStringA(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPSTR)lParam, HIWORD(wParam));;
- break;
- case DFM_GETHELPTEXTW:
- LoadStringW(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPWSTR)lParam, HIWORD(wParam));;
- break;
- case DFM_GETVERBA:
- case DFM_GETVERBW:
- hres = GetVerb((UINT_PTR)(LOWORD(wParam)), (LPSTR)lParam, (UINT)(HIWORD(wParam)), uMsg == DFM_GETVERBW);
- break;
- default:
- hres = E_NOTIMPL;
- break;
- }
- return hres;
- }
- //
- // CBitBucketIDLDropTarget::DragEnter
- //
- // This function puts DROPEFFECT_LINK in *pdwEffect, only if the data object
- // contains one or more net resource.
- //
- STDMETHODIMP CBitBucketIDLDropTarget_DragEnter(IDropTarget *pdropt, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
- {
- CIDLDropTarget *this = IToClass(CIDLDropTarget, dropt, pdropt);
- TraceMsg(TF_BITBUCKET, "Bitbucket: CBitBucketIDLDropTarget::DragEnter");
- // Call the base class first
- CIDLDropTarget_DragEnter(pdropt, pDataObj, grfKeyState, pt, pdwEffect);
- // we don't really care what is in the data object, as long as move
- // is supported by the source we say you can move it to the wastbasket
- // in the case of files we will do the regular recycle bin stuff, if
- // it is not files we will just say it is moved and let the source delete it
- *pdwEffect &= DROPEFFECT_MOVE;
- this->dwEffectLastReturned = *pdwEffect;
- return NOERROR;
- }
- //
- // CBitBucketIDLDropTarget::Drop
- //
- // This function creates a connection to a dropped net resource object.
- //
- STDMETHODIMP CBitBucketIDLDropTarget_Drop(IDropTarget * pdropt, IDataObject * pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
- {
- CIDLDropTarget *this = IToClass(CIDLDropTarget, dropt, pdropt);
- HRESULT hres;
- BOOL fWebFoldersHack;
- // only move operation is allowed
- *pdwEffect &= DROPEFFECT_MOVE;
- fWebFoldersHack = FALSE;
- if (*pdwEffect)
- {
- hres = CIDLDropTarget_DragDropMenu(this, DROPEFFECT_MOVE, pDataObj,
- pt, pdwEffect, NULL, NULL, POPUP_NONDEFAULTDD, grfKeyState);
- if (hres == S_FALSE)
- {
- // let callers know where this is about to go
- // Defview cares where it went so it can handle non-filesys items
- // SHScrap cares because it needs to close the file so we can delete it
- DataObj_SetDropTarget(pDataObj, &CLSID_RecycleBin);
- if (DataObj_GetDWORD(pDataObj, g_cfNotRecyclable, 0))
- {
- if (ShellMessageBox(HINST_THISDLL, NULL,
- MAKEINTRESOURCE(IDS_CONFIRMNOTRECYCLABLE),
- MAKEINTRESOURCE(IDS_RECCLEAN_NAMETEXT),
- MB_SETFOREGROUND | MB_ICONQUESTION | MB_YESNO) == IDNO)
- {
- *pdwEffect = DROPEFFECT_NONE;
- goto lCancel;
- }
- }
- if (this->dwData & DTID_HDROP) // CF_HDROP
- {
- BB_LaunchThread(NULL, this->hwndOwner, pDataObj, DFM_CMD_MOVE);
- // since we will move the file ourself, known as an optimised move,
- // we return zero here. this is per the OLE spec
- *pdwEffect = DROPEFFECT_NONE;
- }
- else
- {
- // if it was not files, we just say we moved the data, letting the
- // source deleted it. lets hope they support undo...
- *pdwEffect = DROPEFFECT_MOVE;
- // HACK: Put up a "you can't undo this" warning for web folders.
- {
- LPIDA pida;
- STGMEDIUM stgmed;
- pida = DataObj_GetHIDA (pDataObj, &stgmed);
- if (pida)
- {
- CLSID clsidSource;
- IPersist *pPers;
- LPCITEMIDLIST pidl;
- pidl = IDA_GetIDListPtr (pida, -1);
- if (pidl)
- {
- hres = SHBindToIDListParent (pidl, &IID_IPersist, (void **) &pPers, NULL);
- if (FAILED(hres))
- {
- IShellFolder *psf;
- hres = SHBindToObject(NULL, &IID_IShellFolder, pidl, (void **) &psf);
- if (SUCCEEDED(hres))
- {
- hres = psf->lpVtbl->QueryInterface (psf, &IID_IPersist, (void **) &pPers);
- psf->lpVtbl->Release(psf);
- }
- }
- if (SUCCEEDED(hres))
- {
- hres = pPers->lpVtbl->GetClassID (pPers, &clsidSource);
- if (SUCCEEDED(hres) &&
- IsEqualGUID (&clsidSource, &CLSID_WebFolders))
- {
- if (ShellMessageBox(HINST_THISDLL, NULL,
- MAKEINTRESOURCE(IDS_CONFIRMNOTRECYCLABLE),
- MAKEINTRESOURCE(IDS_RECCLEAN_NAMETEXT),
- MB_SETFOREGROUND | MB_ICONQUESTION | MB_YESNO) == IDNO)
- {
- *pdwEffect = DROPEFFECT_NONE;
- pPers->lpVtbl->Release(pPers);
- HIDA_ReleaseStgMedium (pida, &stgmed);
- goto lCancel;
- }
- else
- {
- fWebFoldersHack = TRUE;
- }
- }
- pPers->lpVtbl->Release(pPers);
- }
- }
- HIDA_ReleaseStgMedium (pida, &stgmed);
- }
- }
- }
- lCancel:
- if (!fWebFoldersHack)
- {
- DataObj_SetDWORD(pDataObj, g_cfPerformedDropEffect, *pdwEffect);
- DataObj_SetDWORD(pDataObj, g_cfLogicalPerformedDropEffect, DROPEFFECT_MOVE);
- }
- else
- {
- // Make web folders really delete its source file.
- DataObj_SetDWORD (pDataObj, g_cfPerformedDropEffect, 0);
- }
- }
- }
- CIDLDropTarget_DragLeave(pdropt);
- return S_OK;
- }
- const IDropTargetVtbl c_CBBDropTargetVtbl =
- {
- CIDLDropTarget_QueryInterface, CIDLDropTarget_AddRef, CIDLDropTarget_Release,
- CBitBucketIDLDropTarget_DragEnter,
- CIDLDropTarget_DragOver,
- CIDLDropTarget_DragLeave,
- CBitBucketIDLDropTarget_Drop,
- };
- void BBInitializeViewWindow(HWND hwndView)
- {
- int i;
- for (i = 0 ; i < MAX_BITBUCKETS; i++)
- {
- SHChangeNotifyEntry fsne;
- fsne.fRecursive = FALSE;
- // make it if it's there so that we'll get any events
- if (MakeBitBucket(i))
- {
- UINT u;
- fsne.pidl = g_pBitBucket[i]->pidl;
- u = SHChangeNotifyRegister(hwndView,
- SHCNRF_NewDelivery | SHCNRF_ShellLevel | SHCNRF_InterruptLevel,
- SHCNE_DISKEVENTS,
- WM_DSV_FSNOTIFY,
- 1,
- &fsne);
- #ifdef DEBUG
- {
- TCHAR szTemp[MAX_PATH];
- SHGetPathFromIDList(fsne.pidl, szTemp);
- TraceMsg(TF_BITBUCKET, "Bitbucket: SHChangeNotifyRegister returned %d on path %s", u ,szTemp);
- }
- #endif
- }
- }
- }
- HRESULT BBHandleFSNotify(HWND hwnd, LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
- {
- HRESULT hres = S_OK;
- TCHAR szPath[MAX_PATH];
- LPTSTR pszFileName;
- // pidls must be child of drives or network
- // (actually only drives work for right now)
- // that way we won't get duplicate events
- if ((!ILIsParent((LPCITEMIDLIST)&c_idlDrives, pidl1, FALSE) && !ILIsParent((LPCITEMIDLIST)&c_idlNet, pidl1, FALSE)) ||
- (pidl2 && !ILIsParent((LPCITEMIDLIST)&c_idlDrives, pidl2, FALSE) && !ILIsParent((LPCITEMIDLIST)&c_idlNet, pidl2, FALSE)))
- {
- return S_FALSE;
- }
- SHGetPathFromIDList(pidl1, szPath);
- pszFileName = PathFindFileName(szPath);
- if (!lstrcmpi(pszFileName, c_szInfo2) ||
- !lstrcmpi(pszFileName, c_szInfo) ||
- !lstrcmpi(pszFileName, c_szDesktopIni))
- {
- // we ignore changes to these files because they mean we were simply doing bookeeping
- // (eg updating the info file, re-creating the desktop.ini, etc)
- return S_FALSE;
- }
- TraceMsg(TF_BITBUCKET, "Bitbucket: BBHandleFSNotify event %x on path %s", lEvent, szPath);
- switch (lEvent)
- {
- case SHCNE_RENAMEFOLDER:
- case SHCNE_RENAMEITEM:
- {
- int idDrive;
- // if the rename's target is in a bitbucket, then do a create.
- // otherwise, return NOERROR..
- idDrive = DriveIDFromBBPath(szPath);
- if (MakeBitBucket(idDrive) && ILIsParent(g_pBitBucket[idDrive]->pidl, pidl1, TRUE))
- {
- hres = BBHandleFSNotify(hwnd, (lEvent == SHCNE_RENAMEITEM) ? SHCNE_DELETE : SHCNE_RMDIR, pidl1, NULL);
- }
- }
- break;
- case SHCNE_CREATE:
- case SHCNE_MKDIR:
- {
- LPITEMIDLIST pidl;
- pidl = DeletedFilePathToBBPidl(szPath);
- if (pidl)
- {
- ShellFolderView_AddObject(hwnd, pidl);
- hres = S_FALSE;
- }
- }
- break;
- case SHCNE_DELETE:
- case SHCNE_RMDIR:
- {
- // if this was a delete into the recycle bin, pidl2 will exist
- if (pidl2)
- {
- hres = BBHandleFSNotify(hwnd, (lEvent == SHCNE_DELETE) ? SHCNE_CREATE : SHCNE_MKDIR, pidl2, NULL);
- }
- else
- {
- ShellFolderView_RemoveObject(hwnd, ILFindLastID(pidl1));
- hres = S_FALSE;
- }
- }
- break;
- case SHCNE_UPDATEDIR:
- {
- // we recieved an updatedir, which means we probably had more than 10 fsnotify events come in,
- // so we just refresh our brains out.
- ShellFolderView_RefreshAll(hwnd);
- }
- break;
- default:
- {
- // didn't handle this message
- hres = S_FALSE;
- }
- break;
- }
- return hres;
- }
- void BBSort(HWND hwndOwner, int id)
- {
- switch(id)
- {
- case FSIDM_SORTBYNAME:
- ShellFolderView_ReArrange(hwndOwner, 0);
- break;
- case FSIDM_SORTBYORIGIN:
- ShellFolderView_ReArrange(hwndOwner, 1);
- break;
- case FSIDM_SORTBYDELETEDDATE:
- ShellFolderView_ReArrange(hwndOwner, 2);
- break;
- case FSIDM_SORTBYTYPE:
- ShellFolderView_ReArrange(hwndOwner, 3);
- break;
- case FSIDM_SORTBYSIZE:
- ShellFolderView_ReArrange(hwndOwner, 4);
- break;
- }
- }
- HRESULT CALLBACK CBitBucket_DFMCallBackBG(IShellFolder *psf, HWND hwndOwner,
- IDataObject * pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- HRESULT hres = NOERROR;
- switch(uMsg)
- {
- case DFM_MERGECONTEXTMENU:
- if (!(wParam & CMF_DVFILE)) //In the case of the file menu
- CDefFolderMenu_MergeMenu(HINST_THISDLL, POPUP_BITBUCKET_BACKGROUND, POPUP_BITBUCKET_POPUPMERGE, (LPQCMINFO)lParam);
- break;
- case DFM_GETHELPTEXT:
- LoadStringA(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPSTR)lParam, HIWORD(wParam));
- break;
- case DFM_GETHELPTEXTW:
- LoadStringW(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPWSTR)lParam, HIWORD(wParam));
- break;
- case DFM_INVOKECOMMAND:
- switch(wParam)
- {
- case FSIDM_SORTBYNAME:
- case FSIDM_SORTBYORIGIN:
- case FSIDM_SORTBYDELETEDDATE:
- case FSIDM_SORTBYTYPE:
- case FSIDM_SORTBYSIZE:
- BBSort(hwndOwner, (int) wParam);
- break;
- case FSIDM_PROPERTIESBG:
- hres = BB_LaunchThread(NULL, hwndOwner, NULL, FSIDM_PROPERTIESBG);
- break;
- case DFM_CMD_PASTE:
- case DFM_CMD_PROPERTIES:
- // GetAttributesOf cidl==0 has SFGAO_HASPROPSHEET,
- // let defcm handle this
- hres = S_FALSE;
- break;
- default:
- // GetAttributesOf cidl==0 does not set _CANMOVE, _CANDELETE, etc,
- // BUT accelerator keys will get these unavailable menu items...
- // so we need to return failure here
- hres = E_NOTIMPL;
- break;
- }
- break;
- default:
- hres = E_NOTIMPL;
- break;
- }
- return hres;
- }
- STDMETHODIMP CBitBucket_SF_CreateViewObject(IShellFolder2 *psf, HWND hwnd, REFIID riid, void **ppvOut)
- {
- HRESULT hres;
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- if (IsEqualIID(riid, &IID_IShellView))
- {
- SFV_CREATE sSFV;
- sSFV.cbSize = sizeof(sSFV);
- sSFV.pshf = (IShellFolder *)psf;
- sSFV.psvOuter = NULL;
- sSFV.psfvcb = BitBucket_CreateSFVCB((IShellFolder *)psf, this);
- hres = SHCreateShellFolderView(&sSFV, (IShellView**)ppvOut);
- if (sSFV.psfvcb)
- sSFV.psfvcb->lpVtbl->Release(sSFV.psfvcb);
- }
- else if (IsEqualIID(riid, &IID_IDropTarget))
- {
- hres = CIDLDropTarget_Create(hwnd, &c_CBBDropTargetVtbl, this->pidl, (IDropTarget **)ppvOut);
- }
- else if (IsEqualIID(riid, &IID_IContextMenu))
- {
- hres = CDefFolderMenu_Create(NULL, hwnd, 0, NULL, (IShellFolder *)psf, CBitBucket_DFMCallBackBG,
- NULL, NULL, (IContextMenu **)ppvOut);
- }
- else
- {
- *ppvOut = NULL;
- hres = E_NOINTERFACE;
- }
- return hres;
- }
- STDMETHODIMP CBitBucket_SF_ParseDisplayName(IShellFolder2 *psf, HWND hwnd, LPBC pbc,
- LPOLESTR pwszDisplayName, ULONG *pchEaten, LPITEMIDLIST *ppidl, ULONG * pdwAttributes)
- {
- *ppidl = NULL;
- return E_NOTIMPL;
- }
- STDMETHODIMP CBBIDLData_QueryGetData(IDataObject * pdtobj, FORMATETC * pformatetc)
- {
- ASSERT(g_cfFileNameMap);
- if (pformatetc->cfFormat == g_cfFileNameMap && (pformatetc->tymed & TYMED_HGLOBAL))
- {
- return NOERROR; // same as S_OK
- }
- return CFSIDLData_QueryGetData(pdtobj, pformatetc);
- }
- // subclass member function to support CF_HDROP and CF_NETRESOURCE
- // in:
- // hida bitbucket id array
- //
- // out:
- // HGLOBAL with double NULL terminated string list of destination names
- //
- HGLOBAL BuildDestSpecs(LPIDA pida)
- {
- LPCITEMIDLIST pidl;
- LPBBDATAENTRYIDA pbbidl;
- LPTSTR pszRet;
- TCHAR szTemp[MAX_PATH];
- UINT i, cbAlloc = SIZEOF(TCHAR); // for double NULL termination
- for (i = 0; pidl = IDA_GetIDListPtr(pida, i); i++)
- {
- pbbidl = PIDLTODATAENTRYID(pidl);
- BBGetOriginalPath(pbbidl, szTemp, ARRAYSIZE(szTemp));
- cbAlloc += lstrlen(PathFindFileName(szTemp)) * SIZEOF(TCHAR) + SIZEOF(TCHAR);
- }
- pszRet = LocalAlloc(LPTR, cbAlloc);
- if (pszRet)
- {
- LPTSTR pszDest = pszRet;
- for (i = 0; pidl = IDA_GetIDListPtr(pida, i); i++)
- {
- pbbidl = PIDLTODATAENTRYID(pidl);
- BBGetOriginalPath(pbbidl, szTemp, ARRAYSIZE(szTemp));
- lstrcpy(pszDest, PathFindFileName(szTemp));
- pszDest += lstrlen(pszDest) + 1;
- ASSERT((ULONG_PTR)((LPBYTE)pszDest - (LPBYTE)pszRet) < cbAlloc);
- ASSERT(*(pszDest) == 0); // zero init alloc
- }
- ASSERT((LPTSTR)((LPBYTE)pszRet + cbAlloc - SIZEOF(TCHAR)) == pszDest);
- ASSERT(*pszDest == 0); // zero init alloc
- }
- return pszRet;
- }
- extern HRESULT CFSIDLData_GetData(IDataObject * pdtobj, FORMATETC * pformatetcIn, STGMEDIUM * pmedium);
- STDMETHODIMP CBBIDLData_GetData(IDataObject * pdtobj, FORMATETC * pformatetcIn, STGMEDIUM * pmedium)
- {
- HRESULT hres = E_INVALIDARG;
- ASSERT(g_cfFileNameMap);
- if (pformatetcIn->cfFormat == g_cfFileNameMap && (pformatetcIn->tymed & TYMED_HGLOBAL))
- {
- STGMEDIUM medium;
- LPIDA pida = DataObj_GetHIDA(pdtobj, &medium);
- if (medium.hGlobal)
- {
- pmedium->hGlobal = BuildDestSpecs(pida);
- pmedium->tymed = TYMED_HGLOBAL;
- pmedium->pUnkForRelease = NULL;
- HIDA_ReleaseStgMedium(pida, &medium);
- hres = pmedium->hGlobal ? NOERROR : E_OUTOFMEMORY;
- }
- }
- else
- {
- hres = CFSIDLData_GetData(pdtobj, pformatetcIn, pmedium);
- }
- return hres;
- }
- const IDataObjectVtbl c_CBBIDLDataVtbl = {
- CIDLData_QueryInterface, CIDLData_AddRef, CIDLData_Release,
- CBBIDLData_GetData,
- CIDLData_GetDataHere,
- CBBIDLData_QueryGetData,
- CIDLData_GetCanonicalFormatEtc,
- CIDLData_SetData,
- CIDLData_EnumFormatEtc,
- CIDLData_Advise,
- CIDLData_Unadvise,
- CIDLData_EnumAdvise
- };
- HRESULT _CreateDefExtIcon(LPCIDFOLDER pidf, REFIID riid, void **ppxicon)
- {
- HRESULT hres = E_OUTOFMEMORY;
- if (FS_IsFileFolder(pidf))
- {
- return SHCreateDefExtIcon(NULL, II_FOLDER, II_FOLDEROPEN, GIL_PERCLASS, riid, ppxicon);
- }
- else
- {
- DWORD dwFlags = SHGetClassFlags(pidf);
- if (dwFlags & SHCF_ICON_PERINSTANCE)
- {
- TCHAR szPath[MAX_PATH];
- BBGetItemPath(pidf, szPath);
- if (dwFlags & SHCF_HAS_ICONHANDLER)
- {
- LPITEMIDLIST pidlFull = SHSimpleIDListFromPath(szPath);
- if (pidlFull)
- {
- // We hit this case for .lnk files in the recycle bin. We used to call FSLoadHandler
- // but guz decided he only wanted the fstree code using that function (and it takes a fs psf
- // nowdays anyway). So we just bind our brains out.
- hres = SHGetUIObjectFromFullPIDL(pidlFull, NULL, riid, ppxicon);
- ILFree(pidlFull);
- }
- else
- {
- hres = E_OUTOFMEMORY;
- }
- }
- else
- {
- DWORD uid = FS_GetUID(pidf);
- hres = SHCreateDefExtIcon(szPath, uid, uid, GIL_PERINSTANCE | GIL_NOTFILENAME, riid, ppxicon);
- }
- }
- else
- {
- UINT iIcon = (dwFlags & SHCF_ICON_INDEX);
- hres = SHCreateDefExtIcon(c_szStar, iIcon, iIcon, GIL_PERCLASS | GIL_NOTFILENAME, riid, ppxicon);
- }
- return hres;
- }
- }
- STDMETHODIMP CBitBucket_GetUIObjectOf(IShellFolder2 *psf, HWND hwnd, UINT cidl, LPCITEMIDLIST *apidl,
- REFIID riid, UINT *prgfInOut, void **ppvOut)
- {
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- HRESULT hres;
- *ppvOut = NULL;
- if (cidl && IsEqualIID(riid, &IID_IDataObject))
- {
- hres = CIDLData_CreateFromIDArray2(&c_CBBIDLDataVtbl, this->pidl, cidl, apidl, (IDataObject **)ppvOut);
- }
- else if ((cidl == 1) &&
- (IsEqualIID(riid, &IID_IExtractIconA) || IsEqualIID(riid, &IID_IExtractIconW)))
- {
- hres = _CreateDefExtIcon(FS_IsValidID(apidl[0]), riid, ppvOut);
- }
- else if (IsEqualIID(riid, &IID_IContextMenu))
- {
- hres = CDefFolderMenu_Create(this->pidl, hwnd, cidl, apidl,
- (IShellFolder *)psf, CBitBucket_DFMCallBack, NULL, NULL, (IContextMenu**)ppvOut);
- }
- else
- {
- hres = E_NOTIMPL;
- }
- return hres;
- }
- HRESULT FindDataFromBBPidl(LPCITEMIDLIST bbpidl, WIN32_FIND_DATAW *pfd)
- {
- LPBBDATAENTRYIDA pbbdei = PIDLTODATAENTRYID(bbpidl);
- LPIDFOLDER pidf = (LPIDFOLDER)bbpidl;
- ULONGLONG cbSize; // 64 bits
- ZeroMemory(pfd, sizeof(*pfd));
- if (bbpidl->mkid.cb < sizeof(BBDATAENTRYIDA))
- return E_INVALIDARG;
- // this code copied from the size column in details view, so webview will match that
- if (FS_IsFolder(pidf))
- {
- cbSize = pbbdei->bbde.dwSize; // we cache the size of the folder, rounded to cluster
- }
- else
- {
- FS_GetSize(NULL, pidf, &cbSize);
- }
- pfd->nFileSizeHigh = HIDWORD(cbSize);
- pfd->nFileSizeLow = LODWORD(cbSize);
- pfd->dwFileAttributes = pidf->fs.wAttrs; // right?
- DosDateTimeToFileTime(pidf->fs.dateModified, pidf->fs.timeModified, &pfd->ftLastWriteTime);
- return S_OK;
- }
- LPITEMIDLIST BBDataEntryToPidl(int idDrive, LPBBDATAENTRYW pbbde)
- {
- WIN32_FIND_DATA fd;
- TCHAR chDrive;
- TCHAR szPath[MAX_PATH];
- TCHAR szDeletedPath[MAX_PATH];
- TCHAR szOriginalFileName[MAX_PATH];
- LPITEMIDLIST pidl = NULL;
- LPITEMIDLIST pidlRet = NULL;
- BBDATAENTRYIDW bbpidl;
- void *lpv;
- if (g_pBitBucket[idDrive]->fIsUnicode)
- {
- WCHAR szTemp[MAX_PATH];
- // save off the original filename so we have the extension (needed to construct the delete file name)
- SHUnicodeToTChar(pbbde->szOriginal, szOriginalFileName, ARRAYSIZE(szOriginalFileName));
- bbpidl.bbde.iIndex = pbbde->iIndex;
- bbpidl.bbde.idDrive = pbbde->idDrive;
- bbpidl.bbde.ft = pbbde->ft;
- bbpidl.bbde.dwSize = pbbde->dwSize;
- SHAnsiToUnicode(pbbde->szShortName, szTemp, ARRAYSIZE(szTemp));
- if (StrCmpW(pbbde->szOriginal, szTemp) == 0)
- {
- // The short and long names match, so we can use an ansi pidl
- bbpidl.cb = SIZEOF(BBDATAENTRYIDA);
- lpv = &bbpidl.cb;
- }
- else
- {
- // The short and long names DO NOT match, so create a full
- // blown unicode pidl (both ansi and unicode names)
- bbpidl.cb = SIZEOF(BBDATAENTRYIDW);
- StrCpyW(bbpidl.wszOriginal, pbbde->szOriginal);
- lpv = &bbpidl;
- }
- bbpidl.bbde = *((LPBBDATAENTRYA)pbbde);
- }
- else
- {
- LPBBDATAENTRYA pbbdea = (LPBBDATAENTRYA)pbbde;
- // save off the original filename so we have the extension (needed to construct the delete file name)
- SHAnsiToTChar(pbbdea->szOriginal, szOriginalFileName, ARRAYSIZE(szOriginalFileName));
- // just create an ansi pidl
- bbpidl.cb = SIZEOF(BBDATAENTRYIDA);
- bbpidl.bbde = *pbbdea;
- lpv = &bbpidl.cb;
- }
- chDrive = TEXT('a') + pbbde->idDrive;
- if (chDrive == (TEXT('a') + SERVERDRIVE))
- {
- chDrive = TEXT('@');
- }
- DriveIDToBBPath(idDrive, szPath);
- lstrcpyn(szDeletedPath, szPath, ARRAYSIZE(szDeletedPath));
- // create the full path to the delete file so we can get its attributes
- wsprintf(&szDeletedPath[lstrlen(szDeletedPath)], TEXT("\D%c%d%s"), chDrive, pbbde->iIndex, PathFindExtension(szOriginalFileName));
- fd.dwFileAttributes = GetFileAttributes(szDeletedPath);
- if (fd.dwFileAttributes == -1)
- {
- TraceMsg(TF_BITBUCKET, "Bitbucket: unable to get file attributes for path %s , cannot create pidl!!", szDeletedPath);
- return NULL;
- }
- fd.ftCreationTime = pbbde->ft;
- fd.ftLastAccessTime = pbbde->ft;
- fd.ftLastWriteTime = pbbde->ft;
- fd.nFileSizeHigh = 0;
- fd.nFileSizeLow = pbbde->dwSize;
- fd.dwReserved0 = 0;
- fd.dwReserved1 = 0;
- lstrcpyn(fd.cFileName, PathFindFileName(szDeletedPath), ARRAYSIZE(fd.cFileName));
- fd.cAlternateFileName[0] = TEXT(''); // no one uses this anyway...
- SHCreateFSIDList(szPath, &fd, &pidl);
- if (pidl)
- {
- UINT cbSize = ILGetSize(pidl);
- pidlRet = ILResize(pidl, cbSize + bbpidl.cb,0);
- if (pidlRet)
- {
- // Append this BBDATAENTRYID (A or W) onto the end
- memcpy(_ILSkip(pidlRet,cbSize - SIZEOF(pidl->mkid.cb)), lpv, bbpidl.cb);
- // And 0 terminate the thing
- _ILSkip(pidlRet, cbSize + bbpidl.cb - SIZEOF(pidl->mkid.cb))->mkid.cb = 0;
- // Now edit it into one larger id
- pidlRet->mkid.cb += bbpidl.cb;
- ASSERT(ILGetSize(pidlRet) == cbSize + bbpidl.cb);
- }
- }
- return pidlRet;
- }
- __inline int CALLBACK BBFDCompare(void *p1, void *p2, LPARAM lParam)
- {
- return ((LPBBFINDDATA)p1)->iIndex - ((LPBBFINDDATA)p2)->iIndex;
- }
- __inline int CALLBACK BBFDIndexCompare(void *iIndex, void *p2, LPARAM lParam)
- {
- return (int)((INT_PTR)iIndex - ((LPBBFINDDATA)p2)->iIndex);
- }
- BOOL CALLBACK BBEnumDPADestroyCallback(LPVOID pidl, LPVOID pData)
- {
- ILFree(pidl);
- return TRUE;
- }
- LPITEMIDLIST BBEnum_GetNextPidl(LPENUMDELETED ped)
- {
- LPITEMIDLIST pidlRet = FALSE;
- ASSERT(NULL != ped);
- if (NULL == ped->hdpa)
- {
- // This is the first Next() call - so snapshot the info files:
- if (NULL != (ped->hdpa = DPA_CreateEx(0, NULL)))
- {
- int iBitBucket;
- int nItem = 0;
- // loop through the bitbucket drives to find an info file
- for (iBitBucket = 0; iBitBucket < MAX_BITBUCKETS; iBitBucket++)
- {
- if (MakeBitBucket(iBitBucket))
- {
- HANDLE hFile;
- int cDeleted = 0;
- // since we are going to start reading this bitbucket, we take the mrsw
- #ifdef BB_USE_MRSW
- MRSW_EnterRead(g_pBitBucket[iBitBucket]->pmrsw);
- #endif // BB_USE_MRSW
- hFile = OpenBBInfoFile(iBitBucket, OPENBBINFO_WRITE, 0);
- if (INVALID_HANDLE_VALUE != hFile)
- {
- BBDATAENTRYW bbdew;
- DWORD dwDataEntrySize = g_pBitBucket[iBitBucket]->fIsUnicode ? SIZEOF(BBDATAENTRYW) : SIZEOF(BBDATAENTRYA);
- while (ReadNextDataEntry(hFile, &bbdew, FALSE, dwDataEntrySize, iBitBucket))
- {
- LPITEMIDLIST pidl = NULL;
- if (IsDeletedEntry(&bbdew))
- {
- cDeleted++;
- }
- else
- {
- pidl = BBDataEntryToPidl(iBitBucket, &bbdew);
- }
- if (pidl)
- {
- DPA_SetPtr(ped->hdpa, nItem++, pidl);
- }
- }
- if (cDeleted > BB_DELETED_ENTRY_MAX)
- {
- BOOL bTrue = TRUE;
- // set the registry key so that we will compact the info file after the next delete operation
- RegSetValueEx(g_pBitBucket[iBitBucket]->hkeyPerUser, TEXT("NeedToCompact"), 0, REG_DWORD, (LPBYTE)&bTrue, SIZEOF(bTrue));
- }
- CloseBBInfoFile(hFile, iBitBucket);
- }
- #ifdef BB_USE_MRSW
- MRSW_LeaveRead(g_pBitBucket[iBitBucket]->pmrsw);
- #endif // BB_USE_MRSW
- }
- }
- }
- }
- if (NULL != ped->hdpa)
- {
- pidlRet = DPA_GetPtr(ped->hdpa, ped->nItem);
- if (NULL != pidlRet)
- {
- // We're returning an allocated pidl, so replace the pointer
- // in the DPA with NULL so that we don't free it later:
- DPA_SetPtr(ped->hdpa, ped->nItem, NULL);
- }
- else
- {
- // We've reached the end, so destroy our snapshot:
- DPA_DestroyCallback(ped->hdpa, BBEnumDPADestroyCallback, NULL);
- ped->hdpa = NULL;
- }
- ped->nItem++;
- }
- return pidlRet;
- }
- //
- // To be called back from within SHCreateEnumObjects
- //
- HRESULT CALLBACK CBitBucket_EnumCallBack(LPARAM lParam, void *pvData, UINT ecid, UINT index)
- {
- HRESULT hres = NOERROR;
- ENUMDELETED * ped = (ENUMDELETED *)pvData;
- switch (ecid)
- {
- case ECID_SETNEXTID:
- {
- LPITEMIDLIST pidl;
- if (!(ped->grfFlags & SHCONTF_NONFOLDERS))
- return S_FALSE; // "no more element"
- pidl = BBEnum_GetNextPidl(ped);
- if (!pidl)
- {
- hres = S_FALSE; // "no more element"
- }
- else
- {
- CDefEnum_SetReturn(lParam, pidl);
- TraceMsg(TF_BITBUCKET, "Bitbucket: EnumCallBack, returns %S", PIDLTODATAENTRYID(pidl)->bbde.szOriginal);
- //hres = NOERROR; // in success
- }
- break;
- }
- case ECID_RESET:
- if (NULL != ped->hdpa)
- {
- DPA_DestroyCallback(ped->hdpa, BBEnumDPADestroyCallback, NULL);
- ped->hdpa = NULL;
- }
- ped->nItem = 0;
- break;
- case ECID_RELEASE:
- if (NULL != ped->hdpa)
- {
- DPA_DestroyCallback(ped->hdpa, BBEnumDPADestroyCallback, NULL);
- }
- LocalFree((HLOCAL)ped);
- break;
- }
- return hres;
- }
- STDMETHODIMP CBitBucket_SF_EnumObjects(IShellFolder2 *psf, HWND hwndOwner,
- DWORD grfFlags, LPENUMIDLIST * ppenumUnknown)
- {
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- ENUMDELETED * ped = (void*)LocalAlloc(LPTR, SIZEOF(ENUMDELETED));
- if (ped)
- {
- ped->grfFlags = grfFlags;
- ped->pbb = this;
- return SHCreateEnumObjects(hwndOwner, ped, CBitBucket_EnumCallBack, ppenumUnknown);
- }
- return E_OUTOFMEMORY;
- }
- STDMETHODIMP CBitBucket_BindToObject(IShellFolder2 *psf, LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppvOut)
- {
- *ppvOut = NULL;
- return E_NOTIMPL;
- }
- STDMETHODIMP CBitBucket_BindToStorage(IShellFolder2 *psf, LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppvOut)
- {
- *ppvOut = NULL;
- return E_NOTIMPL;
- }
- // get the path name of the file in the file system
- void BBGetItemPath(LPCIDFOLDER pidf, LPTSTR pszPath)
- {
- TCHAR szFile[MAX_PATH];
- LPBBDATAENTRYIDA pbbidl = PIDLTODATAENTRYID(pidf);
- DriveIDToBBPath(pbbidl->bbde.idDrive, pszPath);
- PathAppend(pszPath, FS_CopyName(pidf, szFile, ARRAYSIZE(szFile)));
- }
- // get the friendly looking name of this file
- void BBGetDisplayName(LPCIDFOLDER pidf, LPTSTR pszName)
- {
- TCHAR szTemp[MAX_PATH];
- LPBBDATAENTRYIDA pbbid = PIDLTODATAENTRYID(pidf);
- BBGetOriginalPath(pbbid, szTemp, ARRAYSIZE(szTemp));
- lstrcpy(pszName, PathFindFileName(szTemp));
- if (!FS_ShowExtension(pidf))
- PathRemoveExtension(pszName);
- }
- STDMETHODIMP CBitBucket_SF_GetDisplayNameOf(IShellFolder2 *psf, LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET pStrRet)
- {
- LPCIDFOLDER pidf;
- pStrRet->uType = STRRET_CSTR;
- pStrRet->cStr[0] = 0;
- pidf = FS_IsValidID(pidl);
- if (pidf)
- {
- TCHAR szName[MAX_PATH];
- if (uFlags & SHGDN_FORPARSING)
- BBGetItemPath(pidf, szName);
- else
- BBGetDisplayName(pidf, szName);
- return StringToStrRet(szName, pStrRet);
- }
- return E_INVALIDARG;
- }
- STDMETHODIMP CBitBucket_SetNameOf(IShellFolder2 *psf, HWND hwnd,
- LPCITEMIDLIST pidl, LPCOLESTR lpszName, DWORD dwReserved, LPITEMIDLIST * ppidlOut)
- {
- return E_FAIL;
- }
- STDMETHODIMP CBitBucket_EnumSearches(IShellFolder2 *psf, LPENUMEXTRASEARCH *ppenum)
- {
- *ppenum = NULL;
- return E_NOTIMPL;
- }
- STDMETHODIMP CBitBucket_GetDefaultColumn(IShellFolder2 *psf, DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
- {
- return E_NOTIMPL;
- }
- STDMETHODIMP CBitBucket_GetDefaultColumnState(IShellFolder2 *psf, UINT iColumn, DWORD *pbState)
- {
- return E_NOTIMPL;
- }
- STDMETHODIMP CBitBucket_GetDetailsEx(IShellFolder2 *psf, LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
- {
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- HRESULT hres = E_NOTIMPL;
- if (IsEqualSCID(*pscid, SCID_FINDDATA))
- {
- WIN32_FIND_DATAW wfd;
- hres = FindDataFromBBPidl(pidl, &wfd);
- if (SUCCEEDED(hres))
- {
- hres = InitVariantFromBuffer(pv, (PVOID)&wfd, sizeof(wfd));
- }
- }
- return hres;
- }
- STDMETHODIMP CBitBucket_GetDetailsOf(IShellFolder2 *psf, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *pDetails)
- {
- CBitBucket *this = IToClass(CBitBucket, isf, psf);
- HRESULT hres = NOERROR;
- if (iColumn >= ARRAYSIZE(c_bb_cols))
- return E_NOTIMPL;
- pDetails->str.uType = STRRET_CSTR;
- pDetails->str.cStr[0] = 0;
- if (!pidl)
- {
- // getting the headers
- hres = ResToStrRet(c_bb_cols[iColumn].ids, &pDetails->str);
- pDetails->fmt = c_bb_cols[iColumn].iFmt;
- pDetails->cxChar = c_bb_cols[iColumn].cchCol;
- }
- else
- {
- TCHAR szTemp[MAX_PATH];
- LPCIDFOLDER pidf = FS_IsValidID(pidl);
- UNALIGNED BBDATAENTRYIDA * pbbidl = PIDLTODATAENTRYID(pidl);
- switch (iColumn) {
- case ICOL_NAME:
- BBGetDisplayName(pidf, szTemp);
- hres = StringToStrRet(szTemp, &pDetails->str);
- break;
- case ICOL_SIZE:
- {
- ULONGLONG cbSize;
- if (FS_IsFolder(pidf))
- cbSize = pbbidl->bbde.dwSize;
- else
- FS_GetSize(NULL, pidf, &cbSize);
- StrFormatKBSize(cbSize, szTemp, ARRAYSIZE(szTemp));
- hres = StringToStrRet(szTemp, &pDetails->str);
- }
- break;
- case ICOL_ORIGINAL:
- BBGetOriginalPath(pbbidl, szTemp, ARRAYSIZE(szTemp));
- PathRemoveFileSpec(szTemp);
- hres = StringToStrRet(szTemp, &pDetails->str);
- break;
- case ICOL_TYPE:
- FS_GetTypeName(pidf, szTemp, ARRAYSIZE(szTemp));
- hres = StringToStrRet(szTemp, &pDetails->str);
- break;
- case ICOL_MODIFIED:
- {
- // need stack ft since pbbidl is UNALIGNED
- FILETIME ft = pbbidl->bbde.ft;
- DWORD dwFlags = FDTF_DEFAULT;
- switch (pDetails->fmt)
- {
- case LVCFMT_LEFT_TO_RIGHT :
- dwFlags |= FDTF_LTRDATE;
- break;
- case LVCFMT_RIGHT_TO_LEFT :
- dwFlags |= FDTF_RTLDATE;
- break;
- }
- SHFormatDateTime(&ft, &dwFlags, szTemp, ARRAYSIZE(szTemp));
- hres = StringToStrRet(szTemp, &pDetails->str);
- break;
- }
- }
- }
- return hres;
- }
- STDMETHODIMP CBitBucket_MapColumnToSCID(IShellFolder2 *psf, UINT iColumn, SHCOLUMNID *pscid)
- {
- return MapColumnToSCIDImpl(c_bb_cols, ARRAYSIZE(c_bb_cols), iColumn, pscid);
- }
- IShellFolder2Vtbl c_CBitBucketSFVtbl =
- {
- CBitBucket_SF_QueryInterface, CBitBucket_SF_AddRef, CBitBucket_SF_Release,
- CBitBucket_SF_ParseDisplayName,
- CBitBucket_SF_EnumObjects,
- CBitBucket_BindToObject,
- CBitBucket_BindToStorage,
- CBitBucket_SF_CompareIDs,
- CBitBucket_SF_CreateViewObject,
- CBitBucket_SF_GetAttributesOf,
- CBitBucket_GetUIObjectOf,
- CBitBucket_SF_GetDisplayNameOf,
- CBitBucket_SetNameOf,
- FindFileOrFolders_GetDefaultSearchGUID,
- CBitBucket_EnumSearches,
- CBitBucket_GetDefaultColumn,
- CBitBucket_GetDefaultColumnState,
- CBitBucket_GetDetailsEx,
- CBitBucket_GetDetailsOf,
- CBitBucket_MapColumnToSCID,
- };
- //========================================================================
- // CBitBucket's PersistFile members
- //========================================================================
- STDMETHODIMP CBitBucket_PF_QueryInterface(IPersistFolder2 *ppf, REFIID riid, void **ppvObj)
- {
- CBitBucket *this = IToClass(CBitBucket, ipf, ppf);
- return CBitBucket_SF_QueryInterface(&this->isf, riid, ppvObj);
- }
- STDMETHODIMP_(ULONG) CBitBucket_PF_Release(IPersistFolder2 *ppf)
- {
- CBitBucket *this = IToClass(CBitBucket, ipf, ppf);
- return CBitBucket_SF_Release(&this->isf);
- }
- STDMETHODIMP_(ULONG) CBitBucket_PF_AddRef(IPersistFolder2 *ppf)
- {
- CBitBucket *this = IToClass(CBitBucket, ipf, ppf);
- return CBitBucket_SF_AddRef(&this->isf);
- }
- STDMETHODIMP CBitBucket_PF_GetClassID(IPersistFolder2 *ppf, LPCLSID lpClassID)
- {
- *lpClassID = CLSID_RecycleBin;
- return NOERROR;
- }
- STDMETHODIMP CBitBucket_PF_Initialize(IPersistFolder2 *ppf, LPCITEMIDLIST pidl)
- {
- CBitBucket *this = IToClass(CBitBucket, ipf, ppf);
- ASSERT(this->pidl == NULL);
- this->pidl = ILClone(pidl);
- return this->pidl ? S_OK : E_OUTOFMEMORY;
- }
- STDMETHODIMP CBitBucket_PF_GetCurFolder(IPersistFolder2 *ppf, LPITEMIDLIST *ppidl)
- {
- CBitBucket *this = IToClass(CBitBucket, ipf, ppf);
- return GetCurFolderImpl(this->pidl, ppidl);
- }
- IPersistFolder2Vtbl c_CBitBucketPFVtbl =
- {
- CBitBucket_PF_QueryInterface, CBitBucket_PF_AddRef, CBitBucket_PF_Release,
- CBitBucket_PF_GetClassID,
- CBitBucket_PF_Initialize,
- CBitBucket_PF_GetCurFolder
- };
- STDMETHODIMP CBitBucket_SEI_QueryInterface(IShellExtInit* psei, REFIID riid, void **ppvObj)
- {
- CBitBucket *this = IToClass(CBitBucket, isei, psei);
- return CBitBucket_SF_QueryInterface(&this->isf, riid, ppvObj);
- }
- STDMETHODIMP_(ULONG) CBitBucket_SEI_Release(IShellExtInit* psei)
- {
- CBitBucket *this = IToClass(CBitBucket, isei, psei);
- return CBitBucket_SF_Release(&this->isf);
- }
- STDMETHODIMP_(ULONG) CBitBucket_SEI_AddRef(IShellExtInit* psei)
- {
- CBitBucket *this = IToClass(CBitBucket, isei, psei);
- return CBitBucket_SF_AddRef(&this->isf);
- }
- STDMETHODIMP_(ULONG) CBitBucket_SEI_Initialize(IShellExtInit* psei,
- LPCITEMIDLIST pidlFolder,
- IDataObject * pdtobj, HKEY hkeyProgID)
- {
- return NOERROR;
- }
- STDMETHODIMP CBitBucket_CM_QueryInterface(IContextMenu* pcm, REFIID riid, void **ppvObj)
- {
- CBitBucket *this = IToClass(CBitBucket, icm, pcm);
- return CBitBucket_SF_QueryInterface(&this->isf, riid, ppvObj);
- }
- STDMETHODIMP_(ULONG) CBitBucket_CM_Release(IContextMenu* pcm)
- {
- CBitBucket *this = IToClass(CBitBucket, icm, pcm);
- return CBitBucket_SF_Release(&this->isf);
- }
- STDMETHODIMP_(ULONG) CBitBucket_CM_AddRef(IContextMenu* pcm)
- {
- CBitBucket *this = IToClass(CBitBucket, icm, pcm);
- return CBitBucket_SF_AddRef(&this->isf);
- }
- STDMETHODIMP CBitBucket_QueryContextMenu(IContextMenu * pcm,
- HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast,
- UINT uFlags)
- {
- int idMax = idCmdFirst;
- HMENU hmMerge = SHLoadPopupMenu(HINST_THISDLL, POPUP_BITBUCKET_POPUPMERGE);
- if (hmMerge)
- {
- idMax = Shell_MergeMenus(hmenu, hmMerge, indexMenu, idCmdFirst, idCmdLast, 0);
- if (IsRecycleBinEmpty())
- {
- EnableMenuItem(hmenu, idCmdFirst + FSIDM_PURGEALL, MF_GRAYED | MF_BYCOMMAND);
- }
- DestroyMenu(hmMerge);
- }
- return ResultFromShort(idMax - idCmdFirst);
- }
- STDMETHODIMP CBitBucket_InvokeCommand(IContextMenu* pcm,
- LPCMINVOKECOMMANDINFO pici)
- {
- CBitBucket *this = IToClass(CBitBucket, icm, pcm);
- TraceMsg(TF_BITBUCKET, "Bitbucket: BitBucket_invokeCommand %d %d", pici->lpVerb, FSIDM_PURGEALL);
- switch ((ULONG_PTR)pici->lpVerb)
- {
- case FSIDM_PURGEALL:
- BBPurgeAll(this, pici->hwnd, 0);
- break;
- }
- return NOERROR;
- }
- STDMETHODIMP CBitBucket_GetCommandString(IContextMenu *pcm,
- UINT_PTR idCmd, UINT wFlags, UINT * pwReserved, LPSTR pszName, UINT cchMax)
- {
- TraceMsg(TF_BITBUCKET, "Bitbucket: GetCommandString, idCmd = %d", idCmd);
- switch(wFlags)
- {
- case GCS_VERBA:
- case GCS_VERBW:
- return GetVerb(idCmd, pszName, cchMax, wFlags == GCS_VERBW);
- case GCS_HELPTEXTA:
- return LoadStringA(HINST_THISDLL,
- (UINT)(idCmd + IDS_MH_FSIDM_FIRST),
- pszName, cchMax) ? NOERROR : E_OUTOFMEMORY;
- case GCS_HELPTEXTW:
- return LoadStringW(HINST_THISDLL,
- (UINT)(idCmd + IDS_MH_FSIDM_FIRST),
- (LPWSTR)pszName, cchMax) ? NOERROR : E_OUTOFMEMORY;
- default:
- return E_NOTIMPL;
- }
- }
- STDMETHODIMP CBitBucket_PS_QueryInterface(LPSHELLPROPSHEETEXT pps, REFIID riid,
- void **ppvObj)
- {
- CBitBucket *this = IToClass(CBitBucket, ips, pps);
- return CBitBucket_SF_QueryInterface(&this->isf, riid, ppvObj);
- }
- STDMETHODIMP_(ULONG) CBitBucket_PS_Release(LPSHELLPROPSHEETEXT pps)
- {
- CBitBucket *this = IToClass(CBitBucket, ips, pps);
- return CBitBucket_SF_Release(&this->isf);
- }
- STDMETHODIMP_(ULONG) CBitBucket_PS_AddRef(LPSHELLPROPSHEETEXT pps)
- {
- CBitBucket *this = IToClass(CBitBucket, ips, pps);
- return CBitBucket_SF_AddRef(&this->isf);
- }
- //
- // Callback function that saves the location of the HPROPSHEETPAGE's
- // LPPROPSHEETPAGE so we can pass it to other propsheet pages.
- //
- UINT CALLBACK BBGlobalSettingsCalback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
- {
- LPBBPROPSHEETINFO ppsiTemplate;
- LPBBPROPSHEETINFO ppsiGlobal;
- switch (uMsg)
- {
- case PSPCB_ADDREF:
- // we save off the address of the "real" ppsi in the pGlobal param of the
- // the template, so that the other drives can get to the global page information
- ppsiGlobal = (LPBBPROPSHEETINFO)ppsp;
- ppsiTemplate = (LPBBPROPSHEETINFO)ppsp->lParam;
- ppsiTemplate->pGlobal = ppsiGlobal;
- ppsiGlobal->pGlobal = ppsiGlobal;
- break;
- case PSPCB_CREATE:
- return TRUE; // Yes, please create me
- }
- return 0;
- }
- STDMETHODIMP CBitBucket_PS_AddPages(IShellPropSheetExt * pspx,
- LPFNADDPROPSHEETPAGE lpfnAddPage,
- LPARAM lParam)
- {
- HPROPSHEETPAGE hpage;
- int idDrive;
- int iPage;
- BBPROPSHEETINFO bbpsp;
- TCHAR szTitle[MAX_PATH];
- DWORD dwSize1, dwSize2, dwSize3;
- // read in the global settings
- dwSize1 = SIZEOF(bbpsp.fUseGlobalSettings);
- dwSize2 = SIZEOF(bbpsp.iOriginalPercent);
- dwSize3 = SIZEOF(bbpsp.fOriginalNukeOnDelete);
- if (RegQueryValueEx(g_hkBitBucket, TEXT("UseGlobalSettings"), NULL, NULL, (LPBYTE)&bbpsp.fOriginalUseGlobalSettings, &dwSize1) != ERROR_SUCCESS ||
- RegQueryValueEx(g_hkBitBucket, TEXT("Percent"), NULL, NULL, (LPBYTE)&bbpsp.iOriginalPercent, &dwSize2) != ERROR_SUCCESS ||
- RegQueryValueEx(g_hkBitBucket, TEXT("NukeOnDelete"), NULL, NULL, (LPBYTE)&bbpsp.fOriginalNukeOnDelete, &dwSize3) != ERROR_SUCCESS)
- {
- ASSERTMSG(FALSE, "Bitbucket: could not read global settings from the registry, re-regsvr32 shell32.dll!!");
- bbpsp.fUseGlobalSettings = TRUE;
- bbpsp.iOriginalPercent = 10;
- bbpsp.fOriginalNukeOnDelete = FALSE;
- }
- bbpsp.fUseGlobalSettings = bbpsp.fOriginalUseGlobalSettings;
- bbpsp.fNukeOnDelete = bbpsp.fOriginalNukeOnDelete;
- bbpsp.iPercent = bbpsp.iOriginalPercent;
- bbpsp.psp.dwSize = SIZEOF(bbpsp);
- bbpsp.psp.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
- bbpsp.psp.hInstance = HINST_THISDLL;
- bbpsp.psp.pszTemplate = MAKEINTRESOURCE(DLG_BITBUCKET_GENCONFIG);
- bbpsp.psp.pfnDlgProc = BBGlobalPropDlgProc;
- bbpsp.psp.lParam = (LPARAM)&bbpsp;
- // the callback will fill the bbpsp.pGlobal with the pointer to the "real" psp after it has been copied
- // so that the other drive pages can get to the global information
- bbpsp.psp.pfnCallback = BBGlobalSettingsCalback;
- // add the "Global" settings page
- hpage = CreatePropertySheetPage(&bbpsp.psp);
- #ifdef UNICODE
- // If this assertion fires, it means that comctl32 lost
- // backwards-compatibility with Win95 shell, WinNT4 shell,
- // and IE4 shell, all of which relied on this undocumented
- // behavior.
- ASSERT(bbpsp.pGlobal == (LPBBPROPSHEETINFO)((LPBYTE)hpage + 2 * sizeof(LPVOID)));
- #else
- ASSERT(bbpsp.pGlobal == (LPBBPROPSHEETINFO)hpage);
- #endif
- lpfnAddPage(hpage, lParam);
- // now create the pages for the individual drives
- bbpsp.psp.dwFlags = PSP_USETITLE;
- bbpsp.psp.pszTemplate = MAKEINTRESOURCE(DLG_BITBUCKET_CONFIG);
- bbpsp.psp.pfnDlgProc = BBDriveDlgProc;
- bbpsp.psp.pszTitle = szTitle;
- for (idDrive = 0, iPage = 1; (idDrive < MAX_BITBUCKETS) && (iPage < MAXPROPPAGES); idDrive++)
- {
- if (MakeBitBucket(idDrive))
- {
- dwSize1 = SIZEOF(bbpsp.iOriginalPercent);
- dwSize2 = SIZEOF(bbpsp.fOriginalNukeOnDelete);
- if (RegQueryValueEx(g_pBitBucket[idDrive]->hkey, TEXT("Percent"), NULL, NULL, (LPBYTE)&bbpsp.iOriginalPercent, &dwSize1) != ERROR_SUCCESS ||
- RegQueryValueEx(g_pBitBucket[idDrive]->hkey, TEXT("NukeOnDelete"), NULL, NULL, (LPBYTE)&bbpsp.fOriginalNukeOnDelete, &dwSize2) != ERROR_SUCCESS)
- {
- TraceMsg(TF_BITBUCKET, "Bitbucket: could not read settings from the registry for drive %d, using lame defaults", idDrive);
- bbpsp.iOriginalPercent = 10;
- bbpsp.fNukeOnDelete = FALSE;
- }
- bbpsp.iPercent = bbpsp.iOriginalPercent;
- bbpsp.fNukeOnDelete = bbpsp.fOriginalNukeOnDelete;
- bbpsp.idDrive = idDrive;
- BBGetDriveDisplayName(idDrive, szTitle, ARRAYSIZE(szTitle));
- hpage = CreatePropertySheetPage(&bbpsp.psp);
- lpfnAddPage(hpage, lParam);
- }
- }
- return NOERROR;
- }
- IContextMenuVtbl c_CBitBucketCMVtbl =
- {
- CBitBucket_CM_QueryInterface,
- CBitBucket_CM_AddRef,
- CBitBucket_CM_Release,
- CBitBucket_QueryContextMenu,
- CBitBucket_InvokeCommand,
- CBitBucket_GetCommandString
- };
- IShellPropSheetExtVtbl c_CBitBucketPSVtbl =
- {
- CBitBucket_PS_QueryInterface,
- CBitBucket_PS_AddRef,
- CBitBucket_PS_Release,
- CBitBucket_PS_AddPages,
- CCommonShellPropSheetExt_ReplacePage,
- };
- IShellExtInitVtbl c_CBitBucketSEIVtbl =
- {
- CBitBucket_SEI_QueryInterface,
- CBitBucket_SEI_AddRef,
- CBitBucket_SEI_Release,
- CBitBucket_SEI_Initialize
- };
- HRESULT CBitBucket_CreateInstance(IUnknown* punkOuter, REFIID riid, void **ppvOut)
- {
- HRESULT hres;
- CBitBucket *pbb = (void*)LocalAlloc(LPTR, SIZEOF(CBitBucket));
- if (pbb && InitBBGlobals())
- {
- pbb->isf.lpVtbl = &c_CBitBucketSFVtbl;
- pbb->ipf.lpVtbl = &c_CBitBucketPFVtbl;
- pbb->icm.lpVtbl = &c_CBitBucketCMVtbl;
- pbb->isei.lpVtbl = &c_CBitBucketSEIVtbl;
- pbb->ips.lpVtbl = &c_CBitBucketPSVtbl;
- pbb->cRef = 1;
- hres = CBitBucket_SF_QueryInterface(&pbb->isf, riid, ppvOut);
- CBitBucket_SF_Release(&pbb->isf);
- }
- else
- {
- *ppvOut = NULL;
- hres = E_OUTOFMEMORY;
- }
- return hres;
- }
- //
- // takes a full path to a file in a bucket and creates a pidl for it.
- //
- LPITEMIDLIST DeletedFilePathToBBPidl(LPTSTR pszPath)
- {
- BBDATAENTRYW bbdew;
- LPITEMIDLIST pidl = NULL;
- int idDrive = DriveIDFromBBPath(pszPath);
- int iIndex;
- DWORD dwDataEntrySize;
- HANDLE hFile;
- ASSERT(idDrive >= 0); // general UNC case will generate -1
- iIndex = BBPathToIndex(pszPath);
- if (iIndex == -1)
- return NULL;
- dwDataEntrySize = g_pBitBucket[idDrive]->fIsUnicode ? SIZEOF(BBDATAENTRYW) : SIZEOF(BBDATAENTRYA);
- #ifdef BB_USE_MRSW
- MRSW_EnterRead(g_pBitBucket[idDrive]->pmrsw);
- #endif // BB_USE_MRSW
- hFile = OpenBBInfoFile(idDrive, OPENBBINFO_WRITE, 0);
- if (hFile != INVALID_HANDLE_VALUE)
- {
- // read records (skipping deleted)
- // until we find an index match
- while(ReadNextDataEntry(hFile, &bbdew, TRUE, dwDataEntrySize, idDrive))
- {
- if (bbdew.iIndex == iIndex)
- {
- pidl = BBDataEntryToPidl(idDrive, &bbdew);
- break;
- }
- }
- CloseBBInfoFile(hFile, idDrive);
- }
- #ifdef BB_USE_MRSW
- MRSW_LeaveRead(g_pBitBucket[idDrive]->pmrsw);
- #endif // BB_USE_MRSW
- return pidl;
- }
- BOOL_PTR CALLBACK NewDiskFullDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
- {
- switch (wMsg) {
- case WM_INITDIALOG:
- {
- int idDrive = (int)lParam;
- TCHAR szNewText[MAX_PATH];
- TCHAR szText[MAX_PATH];
- GetDlgItemText(hDlg, IDD_TEXT, szText, ARRAYSIZE(szText));
- wsprintf(szNewText, szText, TEXT('A') + idDrive);
- SetDlgItemText(hDlg, IDD_TEXT, szNewText);
- break;
- }
- case WM_COMMAND:
- switch (GET_WM_COMMAND_ID(wParam, lParam)) {
- case IDC_DISKFULL_CLEANUP:
- case IDCANCEL:
- EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam));
- break;
- }
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- void WINAPI HandleDiskFull(HWND hwnd, int idDrive)
- {
- INT_PTR ret;
- if ((idDrive >= 0) && (idDrive < MAX_DRIVES))
- {
- if (IsBitBucketableDrive(idDrive))
- {
- ret = DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_DISKFULL_NEW),
- hwnd, NewDiskFullDlgProc, (LPARAM)idDrive);
- switch(ret)
- {
- case IDC_DISKFULL_CLEANUP:
- LaunchDiskCleanup(hwnd, idDrive);
- break;
- default:
- break;
- }
- }
- }
- }
- STDAPI_(void) SHHandleDiskFull(HWND hwnd, int idDrive)
- {
- // We will only do anything if noone has created the following named event
- HANDLE hDisable = OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("DisableLowDiskWarning"));
- if (!hDisable)
- {
- if (GetDiskCleanupPath(NULL, 0) && IsBitBucketableDrive(idDrive))
- {
- HandleDiskFull(hwnd, idDrive);
- }
- }
- else
- {
- CloseHandle(hDisable);
- }
- }