- add 2 resource strings

- rewrite recyclebin item handling
- partly implement recycle bin item context menu
- rewrite Trash_CanTrashFile to support volume serial numbers
- recycle bin shows now correct deleted file details for files

svn path=/trunk/; revision=35204
This commit is contained in:
Johannes Anderwald 2008-08-09 01:48:18 +00:00
parent bab735cf05
commit 782a7d5ea7
31 changed files with 546 additions and 158 deletions

View file

@ -625,6 +625,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Ñúçäàâàíåòî íà íîâà ïàïêà å íåâúçìîæíî: íåäîñòàòú÷íè ïðàâà." IDS_CREATEFOLDER_DENIED "Ñúçäàâàíåòî íà íîâà ïàïêà å íåâúçìîæíî: íåäîñòàòú÷íè ïðàâà."
IDS_CREATEFOLDER_CAPTION "Ãðåøêà ïðè ñúçäàâàíå íà íîâà ïàïêà" IDS_CREATEFOLDER_CAPTION "Ãðåøêà ïðè ñúçäàâàíå íà íîâà ïàïêà"

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied." IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"

View file

@ -624,6 +624,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Nelze vytvoøit novou složku, protože pøístup byl odepøen." IDS_CREATEFOLDER_DENIED "Nelze vytvoøit novou složku, protože pøístup byl odepøen."
IDS_CREATEFOLDER_CAPTION "Chyba pøi pokusu vytvoøit nový adresáø" IDS_CREATEFOLDER_CAPTION "Chyba pøi pokusu vytvoøit nový adresáø"

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied." IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"

View file

@ -625,6 +625,8 @@ BEGIN
IDS_COPY "Kopieren" IDS_COPY "Kopieren"
IDS_DELETE "Löschen" IDS_DELETE "Löschen"
IDS_PROPERTIES "Eigenschaften" IDS_PROPERTIES "Eigenschaften"
IDS_CUT "Ausschneiden"
IDS_RESTORE "Wiederherstellen"
IDS_CREATEFOLDER_DENIED "Es konnte kein neues Verzeichnis erstellt werden: Zugriff verweigert." IDS_CREATEFOLDER_DENIED "Es konnte kein neues Verzeichnis erstellt werden: Zugriff verweigert."
IDS_CREATEFOLDER_CAPTION "Es trat ein Fehler beim Erstellen eines neuen Verzeichnisses auf." IDS_CREATEFOLDER_CAPTION "Es trat ein Fehler beim Erstellen eines neuen Verzeichnisses auf."

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Δεν ήταν δυνατή η δημιουργία του φακέλου: Δεν επιτρέπεται η πρόσβαση." IDS_CREATEFOLDER_DENIED "Δεν ήταν δυνατή η δημιουργία του φακέλου: Δεν επιτρέπεται η πρόσβαση."
IDS_CREATEFOLDER_CAPTION "Σφάλμα κατά την δημιουργία νέου φακέλου" IDS_CREATEFOLDER_CAPTION "Σφάλμα κατά την δημιουργία νέου φακέλου"

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied." IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"

View file

@ -606,7 +606,6 @@ BEGIN
IDS_SHV_COLUMN_LOCATION "Location" IDS_SHV_COLUMN_LOCATION "Location"
IDS_SHV_COLUMN_MODEL "Model" IDS_SHV_COLUMN_MODEL "Model"
/* special folders */ /* special folders */
IDS_DESKTOP "Desktop" IDS_DESKTOP "Desktop"
IDS_MYCOMPUTER "My Computer" IDS_MYCOMPUTER "My Computer"
@ -624,6 +623,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied." IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"

View file

@ -624,6 +624,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "No se puede crear nueva carpeta: Permiso denegado." IDS_CREATEFOLDER_DENIED "No se puede crear nueva carpeta: Permiso denegado."
IDS_CREATEFOLDER_CAPTION "Error durante la creación de una nueva carpeta" IDS_CREATEFOLDER_CAPTION "Error durante la creación de una nueva carpeta"

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Uutta kansiota ei voitu luoda: Oikeudet eivät riitä." IDS_CREATEFOLDER_DENIED "Uutta kansiota ei voitu luoda: Oikeudet eivät riitä."
IDS_CREATEFOLDER_CAPTION "Virhe luotaessa uutta kansiota" IDS_CREATEFOLDER_CAPTION "Virhe luotaessa uutta kansiota"

View file

@ -626,6 +626,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Impossible de créer le nouveau dossier : permission refusée." IDS_CREATEFOLDER_DENIED "Impossible de créer le nouveau dossier : permission refusée."
IDS_CREATEFOLDER_CAPTION "Erreur lors de la création du nouveau dossier" IDS_CREATEFOLDER_CAPTION "Erreur lors de la création du nouveau dossier"

View file

@ -625,6 +625,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Nem hozható létre új mappa: Nincs hozzá engedélyed." IDS_CREATEFOLDER_DENIED "Nem hozható létre új mappa: Nincs hozzá engedélyed."
IDS_CREATEFOLDER_CAPTION "Hiba a mappa létrehozásakor" IDS_CREATEFOLDER_CAPTION "Hiba a mappa létrehozásakor"

View file

@ -623,6 +623,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Impossibile creare la cartella: Accesso negato." IDS_CREATEFOLDER_DENIED "Impossibile creare la cartella: Accesso negato."
IDS_CREATEFOLDER_CAPTION "Errore durante la creazione della cartella" IDS_CREATEFOLDER_CAPTION "Errore durante la creazione della cartella"

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "新しいフォルダを作成できませんでした: アクセス権がありません。" IDS_CREATEFOLDER_DENIED "新しいフォルダを作成できませんでした: アクセス権がありません。"
IDS_CREATEFOLDER_CAPTION "新しいフォルダの作成中にエラーが発生しました" IDS_CREATEFOLDER_CAPTION "新しいフォルダの作成中にエラーが発生しました"

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied." IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied." IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"

View file

@ -601,6 +601,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Kunne ikke opprette ny mappe: tilgang nektet." IDS_CREATEFOLDER_DENIED "Kunne ikke opprette ny mappe: tilgang nektet."
IDS_CREATEFOLDER_CAPTION "Klarte ikke opprette ny mappe" IDS_CREATEFOLDER_CAPTION "Klarte ikke opprette ny mappe"

View file

@ -628,6 +628,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Nie mogê utworzyæ nowego katalogu: Brak dostêpu." IDS_CREATEFOLDER_DENIED "Nie mogê utworzyæ nowego katalogu: Brak dostêpu."
IDS_CREATEFOLDER_CAPTION "B³¹d przy tworzeniu nowego katalogu." IDS_CREATEFOLDER_CAPTION "B³¹d przy tworzeniu nowego katalogu."

View file

@ -624,6 +624,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Não pode criar nova pasta: Permissão negada." IDS_CREATEFOLDER_DENIED "Não pode criar nova pasta: Permissão negada."
IDS_CREATEFOLDER_CAPTION "Erro durante a criação da nova pasta" IDS_CREATEFOLDER_CAPTION "Erro durante a criação da nova pasta"

View file

@ -624,6 +624,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Não é possível criar nova pasta: Permissão negada." IDS_CREATEFOLDER_DENIED "Não é possível criar nova pasta: Permissão negada."
IDS_CREATEFOLDER_CAPTION "Erro durante a criação da nova pasta" IDS_CREATEFOLDER_CAPTION "Erro durante a criação da nova pasta"

View file

@ -621,6 +621,8 @@ BEGIN
IDS_COPY "Копировать" IDS_COPY "Копировать"
IDS_DELETE "Удалить" IDS_DELETE "Удалить"
IDS_PROPERTIES "Свойства" IDS_PROPERTIES "Свойства"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Невозможно создать папку - нет полномочий." IDS_CREATEFOLDER_DENIED "Невозможно создать папку - нет полномочий."
IDS_CREATEFOLDER_CAPTION "Ошибка во время создания папки" IDS_CREATEFOLDER_CAPTION "Ошибка во время создания папки"

View file

@ -628,6 +628,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Nie je možné vytvori<72> nový prieèinok: Prístup zamietnutý." IDS_CREATEFOLDER_DENIED "Nie je možné vytvori<72> nový prieèinok: Prístup zamietnutý."
IDS_CREATEFOLDER_CAPTION "Chyba poèas vytvárania nového prieèinka" IDS_CREATEFOLDER_CAPTION "Chyba poèas vytvárania nového prieèinka"

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied." IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied." IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"

View file

@ -622,6 +622,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Yeni dizin oluþturulamýyor: Eriþim engellendi." IDS_CREATEFOLDER_DENIED "Yeni dizin oluþturulamýyor: Eriþim engellendi."
IDS_CREATEFOLDER_CAPTION "Dizin oluþturma sýrasýnda hata" IDS_CREATEFOLDER_CAPTION "Dizin oluþturma sýrasýnda hata"

View file

@ -623,6 +623,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Íå âäàëîñÿ ñòâîðèòè íîâó ïàïêó: ³äìîâà ó äîñòóï³." IDS_CREATEFOLDER_DENIED "Íå âäàëîñÿ ñòâîðèòè íîâó ïàïêó: ³äìîâà ó äîñòóï³."
IDS_CREATEFOLDER_CAPTION "Ïîìèëêà ïðè ñòâîðåíí³ íîâî¿ ïàïêè" IDS_CREATEFOLDER_CAPTION "Ïîìèëêà ïðè ñòâîðåíí³ íîâî¿ ïàïêè"

View file

@ -611,6 +611,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied." IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"

View file

@ -623,6 +623,8 @@ BEGIN
IDS_COPY "Copy" IDS_COPY "Copy"
IDS_DELETE "Delete" IDS_DELETE "Delete"
IDS_PROPERTIES "Properties" IDS_PROPERTIES "Properties"
IDS_CUT "Cut"
IDS_RESTORE "Restore"
IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied." IDS_CREATEFOLDER_DENIED "Unable to create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"

View file

@ -135,6 +135,16 @@ typedef struct tagPIDLPrinterStruct
WCHAR szName[1]; WCHAR szName[1];
}PIDLPrinterStruct; }PIDLPrinterStruct;
typedef struct tagPIDLRecycleStruct
{
FILETIME LastModification;
FILETIME DeletionTime;
ULARGE_INTEGER FileSize;
ULARGE_INTEGER PhysicalFileSize;
DWORD Attributes;
WCHAR szName[1];
}PIDLRecycleStruct;
typedef struct tagGUIDStruct typedef struct tagGUIDStruct
{ {
BYTE dummy; /* offset 01 is unknown */ BYTE dummy; /* offset 01 is unknown */
@ -198,6 +208,7 @@ typedef struct tagPIDLDATA
struct tagValueW valueW; struct tagValueW valueW;
struct tagPIDLFontStruct cfont; struct tagPIDLFontStruct cfont;
struct tagPIDLPrinterStruct cprinter; struct tagPIDLPrinterStruct cprinter;
struct tagPIDLRecycleStruct crecycle;
}u; }u;
} PIDLDATA, *LPPIDLDATA; } PIDLDATA, *LPPIDLDATA;
#include "poppack.h" #include "poppack.h"

View file

@ -77,13 +77,13 @@ static const columninfo RecycleBinColumns[] =
#define COLUMNS_COUNT 6 #define COLUMNS_COUNT 6
static HRESULT FormatDateTime(LPWSTR buffer, int size, FILETIME ft) static HRESULT FormatDateTime(LPWSTR buffer, int size, FILETIME * ft)
{ {
FILETIME lft; FILETIME lft;
SYSTEMTIME time; SYSTEMTIME time;
int ret; int ret;
FileTimeToLocalFileTime(&ft, &lft); FileTimeToLocalFileTime(ft, &lft);
FileTimeToSystemTime(&lft, &time); FileTimeToSystemTime(&lft, &time);
ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, buffer, size); ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, buffer, size);
@ -105,7 +105,7 @@ typedef struct tagRecycleBin
{ {
const IShellFolder2Vtbl *lpVtbl; const IShellFolder2Vtbl *lpVtbl;
const IPersistFolder2Vtbl *lpPersistFolderVtbl; const IPersistFolder2Vtbl *lpPersistFolderVtbl;
const IContextMenuVtbl *lpCmt; const IContextMenu2Vtbl *lpContextMenu2;
const IShellExtInitVtbl *lpSEI; const IShellExtInitVtbl *lpSEI;
LONG refCount; LONG refCount;
@ -114,16 +114,18 @@ typedef struct tagRecycleBin
INT iIdProperties; INT iIdProperties;
LPITEMIDLIST pidl; LPITEMIDLIST pidl;
LPCITEMIDLIST apidl;
} RecycleBin; } RecycleBin;
static const IContextMenuVtbl recycleBincmVtbl; static const IContextMenu2Vtbl recycleBincmVtblFolder;
static const IContextMenu2Vtbl recycleBincmVtblBitbucketItem;
static const IShellFolder2Vtbl recycleBinVtbl; static const IShellFolder2Vtbl recycleBinVtbl;
static const IPersistFolder2Vtbl recycleBinPersistVtbl; static const IPersistFolder2Vtbl recycleBinPersistVtbl;
static const IShellExtInitVtbl eivt; static const IShellExtInitVtbl eivt;
static RecycleBin *impl_from_IContextMenu(IContextMenu *iface) static RecycleBin *impl_from_IContextMenu2(IContextMenu2 *iface)
{ {
return (RecycleBin *)((char *)iface - FIELD_OFFSET(RecycleBin, lpCmt)); return (RecycleBin *)((char *)iface - FIELD_OFFSET(RecycleBin, lpContextMenu2));
} }
static RecycleBin *impl_from_IPersistFolder(IPersistFolder2 *iface) static RecycleBin *impl_from_IPersistFolder(IPersistFolder2 *iface)
@ -152,7 +154,7 @@ HRESULT WINAPI RecycleBin_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *
obj->lpVtbl = &recycleBinVtbl; obj->lpVtbl = &recycleBinVtbl;
obj->lpSEI = &eivt; obj->lpSEI = &eivt;
obj->lpPersistFolderVtbl = &recycleBinPersistVtbl; obj->lpPersistFolderVtbl = &recycleBinPersistVtbl;
obj->lpCmt = &recycleBincmVtbl; obj->lpContextMenu2 = NULL;
if (FAILED(ret = IUnknown_QueryInterface((IUnknown *)obj, riid, ppOutput))) if (FAILED(ret = IUnknown_QueryInterface((IUnknown *)obj, riid, ppOutput)))
{ {
RecycleBin_Destructor(obj); RecycleBin_Destructor(obj);
@ -183,9 +185,11 @@ static HRESULT WINAPI RecycleBin_QueryInterface(IShellFolder2 *iface, REFIID rii
|| IsEqualGUID(riid, &IID_IPersistFolder2)) || IsEqualGUID(riid, &IID_IPersistFolder2))
*ppvObject = &This->lpPersistFolderVtbl; *ppvObject = &This->lpPersistFolderVtbl;
if (IsEqualIID(riid, &IID_IContextMenu)) if (IsEqualIID(riid, &IID_IContextMenu) || IsEqualGUID(riid, &IID_IContextMenu2))
*ppvObject = &This->lpCmt; {
This->lpContextMenu2 = &recycleBincmVtblFolder;
*ppvObject = &This->lpContextMenu2;
}
if(IsEqualIID(riid, &IID_IShellExtInit)) if(IsEqualIID(riid, &IID_IShellExtInit))
{ {
*ppvObject = &(This->lpSEI); *ppvObject = &(This->lpSEI);
@ -237,12 +241,48 @@ UnpackDetailsFromPidl(LPCITEMIDLIST pidl)
return (PDELETED_FILE_DETAILS_W)&pidl->mkid.abID; return (PDELETED_FILE_DETAILS_W)&pidl->mkid.abID;
} }
static LPITEMIDLIST _ILCreateRecycleItem(PDELETED_FILE_DETAILS_W pFileDetails)
{
PIDLDATA tmp;
LPITEMIDLIST pidl;
PIDLRecycleStruct * p;
int size0 = (char*)&tmp.u.crecycle.szName-(char*)&tmp.u.crecycle;
int size = size0;
tmp.type = 0x00;
size += (wcslen(pFileDetails->FileName) + 1) * sizeof(WCHAR);
pidl = (LPITEMIDLIST)SHAlloc(size + 4);
if (!pidl)
return pidl;
pidl->mkid.cb = size+2;
memcpy(pidl->mkid.abID, &tmp, 2+size0);
p = &((PIDLDATA*)pidl->mkid.abID)->u.crecycle;
RtlCopyMemory(p, pFileDetails, sizeof(DELETED_FILE_DETAILS_W));
wcscpy(p->szName, pFileDetails->FileName);
*(WORD*)((char*)pidl+(size+2)) = 0;
return pidl;
}
static PIDLRecycleStruct * _ILGetRecycleStruct(LPCITEMIDLIST pidl)
{
LPPIDLDATA pdata = _ILGetDataPointer(pidl);
if (pdata && pdata->type==0x00)
return (PIDLRecycleStruct*)&(pdata->u.crecycle);
return NULL;
}
BOOL BOOL
WINAPI WINAPI
CBEnumBitBucket(IN PVOID Context, IN HANDLE hDeletedFile) CBEnumBitBucket(IN PVOID Context, IN HANDLE hDeletedFile)
{ {
PDELETED_FILE_DETAILS_W pFileDetails; PDELETED_FILE_DETAILS_W pFileDetails;
DWORD dwSize, dwTotalSize; DWORD dwSize;
LPITEMIDLIST pidl = NULL; LPITEMIDLIST pidl = NULL;
BOOL ret; BOOL ret;
@ -256,29 +296,36 @@ CBEnumBitBucket(IN PVOID Context, IN HANDLE hDeletedFile)
ERR("GetDeletedFileDetailsW failed\n"); ERR("GetDeletedFileDetailsW failed\n");
return FALSE; return FALSE;
} }
dwTotalSize = FIELD_OFFSET(ITEMIDLIST, mkid.abID) + dwSize;
pidl = SHAlloc(dwTotalSize); pFileDetails = SHAlloc(dwSize);
if (!pidl) if (!pFileDetails)
{ {
ERR("No memory\n"); ERR("No memory\n");
return FALSE; return FALSE;
} }
pidl->mkid.cb = dwTotalSize;
pFileDetails = UnpackDetailsFromPidl(pidl);
if (!GetDeletedFileDetailsW(hDeletedFile, if (!GetDeletedFileDetailsW(hDeletedFile,
dwSize, dwSize,
pFileDetails, pFileDetails,
NULL)) NULL))
{ {
ERR("GetDeletedFileDetailsW failed\n"); ERR("GetDeletedFileDetailsW failed\n");
SHFree(pidl); SHFree(pFileDetails);
return FALSE;
}
pidl = _ILCreateRecycleItem(pFileDetails);
if (!pidl)
{
SHFree(pFileDetails);
return FALSE; return FALSE;
} }
ret = AddToEnumList((IEnumIDList*)Context, pidl); ret = AddToEnumList((IEnumIDList*)Context, pidl);
if (!ret)
SHFree(pidl);
SHFree(pFileDetails);
TRACE("Returning %d\n", ret); TRACE("Returning %d\n", ret);
CloseRecycleBinHandle(hDeletedFile); CloseRecycleBinHandle(hDeletedFile);
return ret; return ret;
@ -345,27 +392,42 @@ static HRESULT WINAPI RecycleBin_CompareIDs(IShellFolder2 *iface, LPARAM lParam,
static HRESULT WINAPI RecycleBin_CreateViewObject(IShellFolder2 *iface, HWND hwndOwner, REFIID riid, void **ppv) static HRESULT WINAPI RecycleBin_CreateViewObject(IShellFolder2 *iface, HWND hwndOwner, REFIID riid, void **ppv)
{ {
RecycleBin *This = (RecycleBin *)iface; RecycleBin *This = (RecycleBin *)iface;
HRESULT ret; LPSHELLVIEW pShellView;
HRESULT hr = E_NOINTERFACE;
TRACE("(%p, %p, %s, %p)\n", This, hwndOwner, debugstr_guid(riid), ppv); TRACE("(%p, %p, %s, %p)\n", This, hwndOwner, debugstr_guid(riid), ppv);
if (!ppv)
return hr;
*ppv = NULL; *ppv = NULL;
if (IsEqualGUID(riid, &IID_IShellView))
if (IsEqualIID (riid, &IID_IDropTarget))
{ {
IShellView *tmp; WARN ("IDropTarget not implemented\n");
CSFV sfv; hr = E_NOTIMPL;
ZeroMemory(&sfv, sizeof(sfv));
sfv.cbSize = sizeof(sfv);
sfv.pshf = (IShellFolder *)This;
TRACE("Calling SHCreateShellFolderViewEx\n");
ret = SHCreateShellFolderViewEx(&sfv, &tmp);
TRACE("Result: %08x, output: %p\n", (unsigned int)ret, tmp);
*ppv = tmp;
return ret;
} }
else if (IsEqualIID (riid, &IID_IContextMenu) || IsEqualIID (riid, &IID_IContextMenu2))
{
This->lpContextMenu2 = &recycleBincmVtblFolder;
*ppv = &This->lpContextMenu2;
This->refCount++;
hr = S_OK;
}
else if (IsEqualIID (riid, &IID_IShellView))
{
pShellView = IShellView_Constructor ((IShellFolder *) iface);
if (pShellView)
{
hr = IShellView_QueryInterface (pShellView, riid, ppv);
IShellView_Release (pShellView);
}
}
else
return hr;
TRACE ("-- (%p)->(interface=%p)\n", This, ppv);
return hr;
return E_NOINTERFACE;
} }
static HRESULT WINAPI RecycleBin_GetAttributesOf(IShellFolder2 *This, UINT cidl, LPCITEMIDLIST *apidl, static HRESULT WINAPI RecycleBin_GetAttributesOf(IShellFolder2 *This, UINT cidl, LPCITEMIDLIST *apidl,
@ -376,17 +438,49 @@ static HRESULT WINAPI RecycleBin_GetAttributesOf(IShellFolder2 *This, UINT cidl,
return S_OK; return S_OK;
} }
static HRESULT WINAPI RecycleBin_GetUIObjectOf(IShellFolder2 *This, HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl, static HRESULT WINAPI RecycleBin_GetUIObjectOf(IShellFolder2 *iface, HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl,
REFIID riid, UINT *rgfReserved, void **ppv) REFIID riid, UINT *prgfInOut, void **ppv)
{ {
FIXME("(%p, %p, %d, {%p, ...}, %s, %p, %p): stub!\n", This, hwndOwner, cidl, apidl[0], debugstr_guid(riid), rgfReserved, ppv); IUnknown *pObj = NULL;
HRESULT hr = E_INVALIDARG;
RecycleBin * This = (RecycleBin*)iface;
TRACE ("(%p)->(%p,%u,apidl=%p, %p %p)\n", This,
hwndOwner, cidl, apidl, prgfInOut, ppv);
if (!ppv)
return hr;
*ppv = NULL; *ppv = NULL;
return E_NOTIMPL;
if ((IsEqualIID (riid, &IID_IContextMenu) || IsEqualIID(riid, &IID_IContextMenu2)) && (cidl >= 1))
{
This->lpContextMenu2 = &recycleBincmVtblBitbucketItem;
pObj = (IUnknown*)(&This->lpContextMenu2);
This->apidl = apidl[0];
IUnknown_AddRef(pObj);
hr = S_OK;
}
else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1))
{
hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
}
else
hr = E_NOINTERFACE;
if (SUCCEEDED(hr) && !pObj)
hr = E_OUTOFMEMORY;
*ppv = pObj;
TRACE ("(%p)->hr=0x%08x\n", This, hr);
return hr;
} }
static HRESULT WINAPI RecycleBin_GetDisplayNameOf(IShellFolder2 *This, LPCITEMIDLIST pidl, SHGDNF uFlags, STRRET *pName) static HRESULT WINAPI RecycleBin_GetDisplayNameOf(IShellFolder2 *This, LPCITEMIDLIST pidl, SHGDNF uFlags, STRRET *pName)
{ {
PDELETED_FILE_DETAILS_W pFileDetails; PIDLRecycleStruct *pFileDetails;
LPWSTR pFileName;
TRACE("(%p, %p, %x, %p)\n", This, pidl, (unsigned int)uFlags, pName); TRACE("(%p, %p, %x, %p)\n", This, pidl, (unsigned int)uFlags, pName);
@ -400,12 +494,27 @@ static HRESULT WINAPI RecycleBin_GetDisplayNameOf(IShellFolder2 *This, LPCITEMID
return S_OK; return S_OK;
} }
pFileDetails = UnpackDetailsFromPidl(pidl); pFileDetails = _ILGetRecycleStruct(pidl);
pName->uType = STRRET_WSTR; if (!pFileDetails)
pName->u.pOleStr = StrDupW(&pFileDetails->FileName[0]); {
pName->u.cStr[0] = 0;
pName->uType = STRRET_CSTR;
return E_INVALIDARG;
}
pFileName = wcsrchr(pFileDetails->szName, L'\\');
if (!pFileName)
{
pName->u.cStr[0] = 0;
pName->uType = STRRET_CSTR;
return E_UNEXPECTED;
}
pName->u.pOleStr = StrDupW(pFileName + 1);
if (pName->u.pOleStr == NULL) if (pName->u.pOleStr == NULL)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
pName->uType = STRRET_WSTR;
return S_OK; return S_OK;
} }
@ -416,34 +525,6 @@ static HRESULT WINAPI RecycleBin_SetNameOf(IShellFolder2 *This, HWND hwnd, LPCIT
return E_FAIL; /* not supported */ return E_FAIL; /* not supported */
} }
static HRESULT WINAPI RecycleBin_GetClassID(IPersistFolder2 *This, CLSID *pClassID)
{
TRACE("(%p, %p)\n", This, pClassID);
if (This == NULL || pClassID == NULL)
return E_INVALIDARG;
memcpy(pClassID, &CLSID_RecycleBin, sizeof(CLSID));
return S_OK;
}
static HRESULT WINAPI RecycleBin_Initialize(IPersistFolder2 *iface, LPCITEMIDLIST pidl)
{
RecycleBin *This = impl_from_IPersistFolder(iface);
TRACE("(%p, %p)\n", This, pidl);
This->pidl = ILClone(pidl);
if (This->pidl == NULL)
return E_OUTOFMEMORY;
return S_OK;
}
static HRESULT WINAPI RecycleBin_GetCurFolder(IPersistFolder2 *iface, LPITEMIDLIST *ppidl)
{
RecycleBin *This = impl_from_IPersistFolder(iface);
TRACE("\n");
*ppidl = ILClone(This->pidl);
return S_OK;
}
static HRESULT WINAPI RecycleBin_GetDefaultSearchGUID(IShellFolder2 *iface, GUID *pguid) static HRESULT WINAPI RecycleBin_GetDefaultSearchGUID(IShellFolder2 *iface, GUID *pguid)
{ {
FIXME("stub\n"); FIXME("stub\n");
@ -485,8 +566,11 @@ static HRESULT WINAPI RecycleBin_GetDetailsEx(IShellFolder2 *iface, LPCITEMIDLIS
static HRESULT WINAPI RecycleBin_GetDetailsOf(IShellFolder2 *iface, LPCITEMIDLIST pidl, UINT iColumn, LPSHELLDETAILS pDetails) static HRESULT WINAPI RecycleBin_GetDetailsOf(IShellFolder2 *iface, LPCITEMIDLIST pidl, UINT iColumn, LPSHELLDETAILS pDetails)
{ {
RecycleBin *This = (RecycleBin *)iface; RecycleBin *This = (RecycleBin *)iface;
PDELETED_FILE_DETAILS_W pFileDetails; PIDLRecycleStruct * pFileDetails;
WCHAR buffer[MAX_PATH]; WCHAR buffer[MAX_PATH];
WCHAR szTypeName[100];
LPWSTR pszBackslash;
UINT Length;
TRACE("(%p, %p, %d, %p)\n", This, pidl, iColumn, pDetails); TRACE("(%p, %p, %d, %p)\n", This, pidl, iColumn, pDetails);
if (iColumn >= COLUMNS_COUNT) if (iColumn >= COLUMNS_COUNT)
@ -503,25 +587,38 @@ static HRESULT WINAPI RecycleBin_GetDetailsOf(IShellFolder2 *iface, LPCITEMIDLIS
if (iColumn == COLUMN_NAME) if (iColumn == COLUMN_NAME)
return RecycleBin_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL, &pDetails->str); return RecycleBin_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL, &pDetails->str);
pFileDetails = UnpackDetailsFromPidl(pidl); pFileDetails = _ILGetRecycleStruct(pidl);
switch (iColumn) switch (iColumn)
{ {
case COLUMN_DATEDEL: case COLUMN_DATEDEL:
FormatDateTime(buffer, MAX_PATH, pFileDetails->DeletionTime); FormatDateTime(buffer, MAX_PATH, &pFileDetails->DeletionTime);
break; break;
case COLUMN_DELFROM: case COLUMN_DELFROM:
lstrcpyW(buffer, &pFileDetails->FileName[0]); pszBackslash = wcsrchr(pFileDetails->szName, L'\\');
PathRemoveFileSpecW(buffer); Length = (pszBackslash - pFileDetails->szName);
memcpy((LPVOID)buffer, pFileDetails->szName, Length * sizeof(WCHAR));
buffer[Length] = L'\0';
break; break;
case COLUMN_SIZE: case COLUMN_SIZE:
StrFormatKBSizeW(pFileDetails->FileSize.QuadPart, buffer, MAX_PATH); StrFormatKBSizeW(pFileDetails->FileSize.QuadPart, buffer, MAX_PATH);
break; break;
case COLUMN_MTIME: case COLUMN_MTIME:
FormatDateTime(buffer, MAX_PATH, pFileDetails->LastModification); FormatDateTime(buffer, MAX_PATH, &pFileDetails->LastModification);
break; break;
case COLUMN_TYPE: case COLUMN_TYPE:
/* TODO */ szTypeName[0] = L'\0';
buffer[0] = 0; lstrcpyW(buffer,PathFindExtensionW(pFileDetails->szName));
if (!( HCR_MapTypeToValueW(buffer, buffer, sizeof(buffer)/sizeof(WCHAR), TRUE) &&
HCR_MapTypeToValueW(buffer, szTypeName, sizeof(szTypeName)/sizeof(WCHAR), FALSE )))
{
lstrcpyW (szTypeName, PathFindExtensionW(pFileDetails->szName));
strcatW(szTypeName, L"-");
Length = wcslen(szTypeName);
if (LoadStringW(shell32_hInstance, IDS_SHV_COLUMN1, &szTypeName[Length], (sizeof(szTypeName)/sizeof(WCHAR))- Length))
szTypeName[(sizeof(szTypeName)/sizeof(WCHAR))-1] = L'\0';
}
pDetails->str.uType = STRRET_WSTR;
return SHStrDupW(szTypeName, &pDetails->str.u.pOleStr);
break; break;
default: default:
return E_FAIL; return E_FAIL;
@ -571,6 +668,34 @@ static const IShellFolder2Vtbl recycleBinVtbl =
RecycleBin_MapColumnToSCID RecycleBin_MapColumnToSCID
}; };
static HRESULT WINAPI RecycleBin_IPersistFolder2_GetClassID(IPersistFolder2 *This, CLSID *pClassID)
{
TRACE("(%p, %p)\n", This, pClassID);
if (This == NULL || pClassID == NULL)
return E_INVALIDARG;
memcpy(pClassID, &CLSID_RecycleBin, sizeof(CLSID));
return S_OK;
}
static HRESULT WINAPI RecycleBin_IPersistFolder2_Initialize(IPersistFolder2 *iface, LPCITEMIDLIST pidl)
{
RecycleBin *This = impl_from_IPersistFolder(iface);
TRACE("(%p, %p)\n", This, pidl);
This->pidl = ILClone(pidl);
if (This->pidl == NULL)
return E_OUTOFMEMORY;
return S_OK;
}
static HRESULT WINAPI RecycleBin_IPersistFolder2_GetCurFolder(IPersistFolder2 *iface, LPITEMIDLIST *ppidl)
{
RecycleBin *This = impl_from_IPersistFolder(iface);
TRACE("\n");
*ppidl = ILClone(This->pidl);
return S_OK;
}
static HRESULT WINAPI RecycleBin_IPersistFolder2_QueryInterface(IPersistFolder2 *This, REFIID riid, void **ppvObject) static HRESULT WINAPI RecycleBin_IPersistFolder2_QueryInterface(IPersistFolder2 *This, REFIID riid, void **ppvObject)
{ {
return RecycleBin_QueryInterface((IShellFolder2 *)impl_from_IPersistFolder(This), riid, ppvObject); return RecycleBin_QueryInterface((IShellFolder2 *)impl_from_IPersistFolder(This), riid, ppvObject);
@ -594,23 +719,13 @@ static const IPersistFolder2Vtbl recycleBinPersistVtbl =
RecycleBin_IPersistFolder2_Release, RecycleBin_IPersistFolder2_Release,
/* IPersist */ /* IPersist */
RecycleBin_GetClassID, RecycleBin_IPersistFolder2_GetClassID,
/* IPersistFolder */ /* IPersistFolder */
RecycleBin_Initialize, RecycleBin_IPersistFolder2_Initialize,
/* IPersistFolder2 */ /* IPersistFolder2 */
RecycleBin_GetCurFolder RecycleBin_IPersistFolder2_GetCurFolder
}; };
/*************************************************************************
* SHUpdateRecycleBinIcon [SHELL32.@]
*
* Undocumented
*/
HRESULT WINAPI SHUpdateRecycleBinIcon(void)
{
FIXME("stub\n");
return S_OK;
}
/************************************************************************* /*************************************************************************
* BitBucket IShellExtInit interface * BitBucket IShellExtInit interface
*/ */
@ -659,31 +774,31 @@ static const IShellExtInitVtbl eivt =
*/ */
static HRESULT WINAPI static HRESULT WINAPI
RecycleBin_IContextMenu_QueryInterface( IContextMenu* iface, REFIID riid, void** ppvObject ) RecycleBin_IContextMenu2Folder_QueryInterface( IContextMenu2* iface, REFIID riid, void** ppvObject )
{ {
return RecycleBin_QueryInterface((IShellFolder2 *)impl_from_IContextMenu(iface), riid, ppvObject); return RecycleBin_QueryInterface((IShellFolder2 *)impl_from_IContextMenu2(iface), riid, ppvObject);
} }
static ULONG WINAPI static ULONG WINAPI
RecycleBin_IContextMenu_AddRef( IContextMenu* iface ) RecycleBin_IContextMenu2Folder_AddRef( IContextMenu2* iface )
{ {
return RecycleBin_AddRef((IShellFolder2 *)impl_from_IContextMenu(iface)); return RecycleBin_AddRef((IShellFolder2 *)impl_from_IContextMenu2(iface));
} }
static ULONG WINAPI static ULONG WINAPI
RecycleBin_IContextMenu_Release( IContextMenu* iface ) RecycleBin_IContextMenu2Folder_Release( IContextMenu2* iface )
{ {
return RecycleBin_Release((IShellFolder2 *)impl_from_IContextMenu(iface)); return RecycleBin_Release((IShellFolder2 *)impl_from_IContextMenu2(iface));
} }
static HRESULT WINAPI static HRESULT WINAPI
RecycleBin_IContextMenu_QueryContextMenu( IContextMenu* iface, HMENU hmenu, UINT indexMenu, RecycleBin_IContextMenu2Folder_QueryContextMenu( IContextMenu2* iface, HMENU hmenu, UINT indexMenu,
UINT idCmdFirst, UINT idCmdLast, UINT uFlags ) UINT idCmdFirst, UINT idCmdLast, UINT uFlags )
{ {
WCHAR szBuffer[100]; WCHAR szBuffer[100];
MENUITEMINFOW mii; MENUITEMINFOW mii;
int id = 1; int id = 1;
RecycleBin * This = impl_from_IContextMenu(iface); RecycleBin * This = impl_from_IContextMenu2(iface);
TRACE("%p %p %u %u %u %u\n", This, TRACE("%p %p %u %u %u %u\n", This,
hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags ); hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags );
@ -715,7 +830,7 @@ RecycleBin_IContextMenu_QueryContextMenu( IContextMenu* iface, HMENU hmenu, UINT
mii.wID = idCmdFirst + id++; mii.wID = idCmdFirst + id++;
if (!InsertMenuItemW( hmenu, idCmdLast, TRUE, &mii )) if (!InsertMenuItemW( hmenu, idCmdLast, TRUE, &mii ))
{ {
TRACE("RecycleBin_IContextMenu_QueryContextMenu failed to insert item properties"); TRACE("RecycleBin_IContextMenu2Folder_QueryContextMenu failed to insert item properties");
return E_FAIL; return E_FAIL;
} }
This->iIdEmpty = 2; This->iIdEmpty = 2;
@ -723,13 +838,13 @@ RecycleBin_IContextMenu_QueryContextMenu( IContextMenu* iface, HMENU hmenu, UINT
} }
static HRESULT WINAPI static HRESULT WINAPI
RecycleBin_IContextMenu_InvokeCommand( IContextMenu* iface, LPCMINVOKECOMMANDINFO lpici ) RecycleBin_IContextMenu2Folder_InvokeCommand( IContextMenu2* iface, LPCMINVOKECOMMANDINFO lpici )
{ {
HRESULT hr; HRESULT hr;
LPSHELLBROWSER lpSB; LPSHELLBROWSER lpSB;
LPSHELLVIEW lpSV = NULL; LPSHELLVIEW lpSV = NULL;
RecycleBin * This = impl_from_IContextMenu(iface); RecycleBin * This = impl_from_IContextMenu2(iface);
TRACE("%p %p verb %p\n", This, lpici, lpici->lpVerb); TRACE("%p %p verb %p\n", This, lpici, lpici->lpVerb);
@ -765,10 +880,10 @@ RecycleBin_IContextMenu_InvokeCommand( IContextMenu* iface, LPCMINVOKECOMMANDINF
} }
static HRESULT WINAPI static HRESULT WINAPI
RecycleBin_IContextMenu_GetCommandString( IContextMenu* iface, UINT_PTR idCmd, UINT uType, RecycleBin_IContextMenu2Folder_GetCommandString( IContextMenu2* iface, UINT_PTR idCmd, UINT uType,
UINT* pwReserved, LPSTR pszName, UINT cchMax ) UINT* pwReserved, LPSTR pszName, UINT cchMax )
{ {
RecycleBin * This = impl_from_IContextMenu(iface); RecycleBin * This = impl_from_IContextMenu2(iface);
FIXME("%p %lu %u %p %p %u\n", This, FIXME("%p %lu %u %p %p %u\n", This,
idCmd, uType, pwReserved, pszName, cchMax ); idCmd, uType, pwReserved, pszName, cchMax );
@ -776,16 +891,190 @@ RecycleBin_IContextMenu_GetCommandString( IContextMenu* iface, UINT_PTR idCmd, U
return E_NOTIMPL; return E_NOTIMPL;
} }
static const IContextMenuVtbl recycleBincmVtbl = /**************************************************************************
* RecycleBin_IContextMenu2Item_HandleMenuMsg()
*/
static HRESULT WINAPI RecycleBin_IContextMenu2Folder_HandleMenuMsg(
IContextMenu2 *iface,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{ {
RecycleBin_IContextMenu_QueryInterface, RecycleBin * This = impl_from_IContextMenu2(iface);
RecycleBin_IContextMenu_AddRef,
RecycleBin_IContextMenu_Release, TRACE("RecycleBin_IContextMenu2Item_IContextMenu2Folder_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam);
RecycleBin_IContextMenu_QueryContextMenu,
RecycleBin_IContextMenu_InvokeCommand, return E_NOTIMPL;
RecycleBin_IContextMenu_GetCommandString }
static const IContextMenu2Vtbl recycleBincmVtblFolder =
{
RecycleBin_IContextMenu2Folder_QueryInterface,
RecycleBin_IContextMenu2Folder_AddRef,
RecycleBin_IContextMenu2Folder_Release,
RecycleBin_IContextMenu2Folder_QueryContextMenu,
RecycleBin_IContextMenu2Folder_InvokeCommand,
RecycleBin_IContextMenu2Folder_GetCommandString,
RecycleBin_IContextMenu2Folder_HandleMenuMsg
}; };
/**************************************************************************
* IContextMenu2 Bitbucket Item Implementation
*/
/************************************************************************
* RecycleBin_IContextMenu2Item_QueryInterface
*/
static HRESULT WINAPI RecycleBin_IContextMenu2Item_QueryInterface(IContextMenu2 * iface, REFIID iid, LPVOID * ppvObject)
{
RecycleBin * This = impl_from_IContextMenu2(iface);
TRACE("(%p)\n", This);
return RecycleBin_QueryInterface((IShellFolder2*)This, iid, ppvObject);
}
/************************************************************************
* RecycleBin_IContextMenu2Item_AddRef
*/
static ULONG WINAPI RecycleBin_IContextMenu2Item_AddRef(IContextMenu2 * iface)
{
RecycleBin * This = impl_from_IContextMenu2(iface);
TRACE("(%p)->(count=%u)\n", This, This->refCount);
return RecycleBin_AddRef((IShellFolder2*)This);
}
/************************************************************************
* RecycleBin_IContextMenu2Item_Release
*/
static ULONG WINAPI RecycleBin_IContextMenu2Item_Release(IContextMenu2 * iface)
{
RecycleBin * This = impl_from_IContextMenu2(iface);
TRACE("(%p)->(count=%u)\n", This, This->refCount);
return RecycleBin_Release((IShellFolder2*)This);
}
/**************************************************************************
* RecycleBin_IContextMenu2Item_QueryContextMenu()
*/
static HRESULT WINAPI RecycleBin_IContextMenu2Item_QueryContextMenu(
IContextMenu2 *iface,
HMENU hMenu,
UINT indexMenu,
UINT idCmdFirst,
UINT idCmdLast,
UINT uFlags)
{
char szBuffer[30] = {0};
ULONG Count = 1;
RecycleBin * This = impl_from_IContextMenu2(iface);
TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
if (LoadStringA(shell32_hInstance, IDS_RESTORE, szBuffer, sizeof(szBuffer)/sizeof(char)))
{
szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0';
_InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED);
Count++;
}
if (LoadStringA(shell32_hInstance, IDS_CUT, szBuffer, sizeof(szBuffer)/sizeof(char)))
{
_InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0';
_InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED);
}
if (LoadStringA(shell32_hInstance, IDS_DELETE, szBuffer, sizeof(szBuffer)/sizeof(char)))
{
szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0';
_InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
_InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED);
}
if (LoadStringA(shell32_hInstance, IDS_PROPERTIES, szBuffer, sizeof(szBuffer)/sizeof(char)))
{
szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0';
_InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
_InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT);
}
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count);
}
/**************************************************************************
* RecycleBin_IContextMenu2Item_InvokeCommand()
*/
static HRESULT WINAPI RecycleBin_IContextMenu2Item_InvokeCommand(
IContextMenu2 *iface,
LPCMINVOKECOMMANDINFO lpcmi)
{
RecycleBin * This = impl_from_IContextMenu2(iface);
TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
return S_OK;
}
/**************************************************************************
* RecycleBin_IContextMenu2Item_GetCommandString()
*
*/
static HRESULT WINAPI RecycleBin_IContextMenu2Item_GetCommandString(
IContextMenu2 *iface,
UINT_PTR idCommand,
UINT uFlags,
UINT* lpReserved,
LPSTR lpszName,
UINT uMaxNameLen)
{
RecycleBin * This = impl_from_IContextMenu2(iface);
TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
return E_FAIL;
}
/**************************************************************************
* RecycleBin_IContextMenu2Item_HandleMenuMsg()
*/
static HRESULT WINAPI RecycleBin_IContextMenu2Item_HandleMenuMsg(
IContextMenu2 *iface,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
RecycleBin * This = impl_from_IContextMenu2(iface);
TRACE("RecycleBin_IContextMenu2Item_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam);
return E_NOTIMPL;
}
static const IContextMenu2Vtbl recycleBincmVtblBitbucketItem =
{
RecycleBin_IContextMenu2Item_QueryInterface,
RecycleBin_IContextMenu2Item_AddRef,
RecycleBin_IContextMenu2Item_Release,
RecycleBin_IContextMenu2Item_QueryContextMenu,
RecycleBin_IContextMenu2Item_InvokeCommand,
RecycleBin_IContextMenu2Item_GetCommandString,
RecycleBin_IContextMenu2Item_HandleMenuMsg
};
void toggleNukeOnDeleteOption(HWND hwndDlg, BOOL bEnable) void toggleNukeOnDeleteOption(HWND hwndDlg, BOOL bEnable)
{ {
if (bEnable) if (bEnable)
@ -989,58 +1278,78 @@ BOOL SH_ShowRecycleBinProperties(WCHAR sDrive)
BOOL BOOL
TRASH_CanTrashFile(LPCWSTR wszPath) TRASH_CanTrashFile(LPCWSTR wszPath)
{ {
LONG res; LONG ret;
DWORD dwNukeOnDelete, dwType, VolSerialNumber, MaxComponentLength;
DWORD FileSystemFlags, dwSize, dwDisposition;
HKEY hKey; HKEY hKey;
DWORD RegSerial, dwNukeOnDelete, dwType; WCHAR szBuffer[10];
DWORD dwLength; WCHAR szKey[150] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\";
static WCHAR szKey[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\c";
if (wszPath[1] != L':') if (wszPath[1] != L':')
{ {
/* path is UNC */ /* path is UNC */
return FALSE; return FALSE;
} }
szKey[62] = wszPath[0]; if (GetDriveTypeW(wszPath) != DRIVE_FIXED)
res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hKey);
if (res != ERROR_SUCCESS)
{ {
FIXME("Failed to open registry path\n"); /* no bitbucket on removable media */
return FALSE;
}
dwLength = sizeof(RegSerial);
res = RegQueryValueExW(hKey, L"VolumeSerialNumber", NULL, &dwType, (LPBYTE)&RegSerial, &dwLength);
if (res == ERROR_SUCCESS)
{
DWORD FileSystemFlags, MaxComponentLength, VolSerialNumber;
GetVolumeInformationW(wszPath, NULL, 0, &VolSerialNumber, &MaxComponentLength, &FileSystemFlags, NULL, 0);
if (VolSerialNumber != RegSerial)
{
/* FIXME
* the current volume was mounted on a different path
*/
FIXME("mismatched serial volume number\n");
RegCloseKey(hKey);
return FALSE;
}
}
dwLength = sizeof(dwNukeOnDelete);
res = RegQueryValueExW(hKey, L"NukeOnDelete", NULL, &dwType, (LPBYTE)&dwNukeOnDelete, &dwLength);
if (res == ERROR_SUCCESS && dwNukeOnDelete == 0x0)
{
RegCloseKey(hKey);
return FALSE; return FALSE;
} }
/* FIXME if (!GetVolumeInformationW(wszPath, NULL, 0, &VolSerialNumber, &MaxComponentLength, &FileSystemFlags, NULL, 0))
* check if trash is already full {
*/ ERR("GetVolumeInformationW failed with %u\n", GetLastError());
return FALSE;
}
sprintfW(szBuffer, L"%04X-%04X", LOWORD(VolSerialNumber), HIWORD(VolSerialNumber));
wcscat(szKey, szBuffer);
if (RegCreateKeyExW(HKEY_CURRENT_USER, szBuffer, 0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS)
{
ERR("RegCreateKeyExW failed\n");
return FALSE;
}
if (dwDisposition & REG_CREATED_NEW_KEY)
{
/* per default move to bitbucket */
dwNukeOnDelete = 0;
RegSetValueExW(hKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&dwNukeOnDelete, sizeof(DWORD));
/* per default unlimited size */
dwSize = -1;
RegSetValueExW(hKey, L"MaxSize", 0, REG_DWORD, (LPBYTE)&dwSize, sizeof(DWORD));
RegCloseKey(hKey); RegCloseKey(hKey);
return TRUE; return TRUE;
}
else
{
dwSize = sizeof(dwNukeOnDelete);
ret = RegQueryValueExW(hKey, L"NukeOnDelete", NULL, &dwType, (LPBYTE)&dwNukeOnDelete, &dwSize);
if (ret != ERROR_SUCCESS)
{
sprintfW(szBuffer, L"ret %u\n", ret);
MessageBoxW(NULL, szBuffer, NULL, MB_OK);
RegCloseKey(hKey);
if (ret == ERROR_FILE_NOT_FOUND)
{
/* restore key and enable bitbucket */
dwNukeOnDelete = 0;
RegSetValueExW(hKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&dwNukeOnDelete, sizeof(DWORD));
}
return TRUE;
}
else if (dwNukeOnDelete)
{
/* do not delete to bitbucket */
return FALSE;
}
/* FIXME
* check if bitbucket is full
*/
return TRUE;
}
} }
BOOL BOOL
@ -1049,3 +1358,14 @@ TRASH_TrashFile(LPCWSTR wszPath)
TRACE("(%s)\n", debugstr_w(wszPath)); TRACE("(%s)\n", debugstr_w(wszPath));
return DeleteFileToRecycleBinW(wszPath); return DeleteFileToRecycleBinW(wszPath);
} }
/*************************************************************************
* SHUpdateRecycleBinIcon [SHELL32.@]
*
* Undocumented
*/
HRESULT WINAPI SHUpdateRecycleBinIcon(void)
{
FIXME("stub\n");
return S_OK;
}

View file

@ -158,6 +158,8 @@
#define IDS_SHV_COLUMN_COMMENTS 320 #define IDS_SHV_COLUMN_COMMENTS 320
#define IDS_SHV_COLUMN_LOCATION 321 #define IDS_SHV_COLUMN_LOCATION 321
#define IDS_SHV_COLUMN_MODEL 322 #define IDS_SHV_COLUMN_MODEL 322
#define IDS_CUT 323
#define IDS_RESTORE 324
/* Note: this string is referenced from the registry */ /* Note: this string is referenced from the registry */
#define IDS_RECYCLEBIN_FOLDER_NAME 8964 #define IDS_RECYCLEBIN_FOLDER_NAME 8964