Jay Yang : shell32: Implement restoring items from the recycle bin.
Alexandre Julliard
julliard at winehq.org
Mon Jul 11 13:17:47 CDT 2011
Module: wine
Branch: master
Commit: 80c62ca20349582e339fbc398be35b9a8cff6d01
URL: http://source.winehq.org/git/wine.git/?a=commit;h=80c62ca20349582e339fbc398be35b9a8cff6d01
Author: Jay Yang <jkelleyy at gmail.com>
Date: Fri Jul 8 10:47:08 2011 -0400
shell32: Implement restoring items from the recycle bin.
---
dlls/shell32/recyclebin.c | 49 +++++++++++++++++++++++++++++++++++++++++++++
dlls/shell32/trash.c | 33 ++++++++++++++++++++++++++++++
dlls/shell32/xdg.h | 1 +
3 files changed, 83 insertions(+), 0 deletions(-)
diff --git a/dlls/shell32/recyclebin.c b/dlls/shell32/recyclebin.c
index a98bc09..f840bf1 100644
--- a/dlls/shell32/recyclebin.c
+++ b/dlls/shell32/recyclebin.c
@@ -186,6 +186,52 @@ static void DoErase(RecycleBinMenu *This)
ISFHelper_DeleteItems(helper,This->cidl,(LPCITEMIDLIST*)This->apidl);
}
+static void DoRestore(RecycleBinMenu *This)
+{
+
+ /*TODO add prompts*/
+ UINT i;
+ for(i=0;i<This->cidl;i++)
+ {
+ WIN32_FIND_DATAW data;
+ TRASH_UnpackItemID(&((This->apidl[i])->mkid),&data);
+ if(PathFileExistsW(data.cFileName))
+ {
+ PIDLIST_ABSOLUTE dest_pidl = ILCreateFromPathW(data.cFileName);
+ WCHAR message[100];
+ WCHAR caption[50];
+ if(_ILIsFolder(ILFindLastID(dest_pidl)))
+ LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_OVERWRITEFOLDER,
+ message,sizeof(message)/sizeof(WCHAR));
+ else
+ LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_OVERWRITEFILE,
+ message,sizeof(message)/sizeof(WCHAR));
+ LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_OVERWRITE_CAPTION,
+ caption,sizeof(caption)/sizeof(WCHAR));
+
+ if(ShellMessageBoxW(shell32_hInstance,GetActiveWindow(),message,
+ caption,MB_YESNO|MB_ICONEXCLAMATION,
+ data.cFileName)!=IDYES)
+ continue;
+ }
+ if(SUCCEEDED(TRASH_RestoreItem(This->apidl[i])))
+ {
+ IPersistFolder2 *persist;
+ LPITEMIDLIST root_pidl;
+ PIDLIST_ABSOLUTE dest_pidl = ILCreateFromPathW(data.cFileName);
+ BOOL is_folder = _ILIsFolder(ILFindLastID(dest_pidl));
+ IShellFolder2_QueryInterface(This->folder,&IID_IPersistFolder2,
+ (void**)&persist);
+ IPersistFolder2_GetCurFolder(persist,&root_pidl);
+ SHChangeNotify(is_folder ? SHCNE_RMDIR : SHCNE_DELETE,
+ SHCNF_IDLIST,ILCombine(root_pidl,This->apidl[i]),0);
+ SHChangeNotify(is_folder ? SHCNE_MKDIR : SHCNE_CREATE,
+ SHCNF_IDLIST,dest_pidl,0);
+ ILFree(dest_pidl);
+ ILFree(root_pidl);
+ }
+ }
+}
static HRESULT WINAPI RecycleBinMenu_InvokeCommand(IContextMenu2 *iface,
LPCMINVOKECOMMANDINFO pici)
@@ -199,6 +245,9 @@ static HRESULT WINAPI RecycleBinMenu_InvokeCommand(IContextMenu2 *iface,
case IDM_RECYCLEBIN_ERASE:
DoErase(This);
break;
+ case IDM_RECYCLEBIN_RESTORE:
+ DoRestore(This);
+ break;
default:
return E_NOTIMPL;
}
diff --git a/dlls/shell32/trash.c b/dlls/shell32/trash.c
index c449dce..c64e203 100644
--- a/dlls/shell32/trash.c
+++ b/dlls/shell32/trash.c
@@ -544,6 +544,39 @@ failed:
return err;
}
+HRESULT TRASH_RestoreItem(LPCITEMIDLIST pidl){
+ int suffix_length = strlen(trashinfo_suffix);
+ LPCSHITEMID id = &(pidl->mkid);
+ const char *bucket_name = (const char*)(id->abID+1+sizeof(WIN32_FIND_DATAW));
+ const char *filename = (const char*)(id->abID+1+sizeof(WIN32_FIND_DATAW)+strlen(bucket_name)+1);
+ char *restore_path;
+ WIN32_FIND_DATAW data;
+ char *file_path;
+
+ TRACE("(%p)",pidl);
+ if(strcmp(filename+strlen(filename)-suffix_length,trashinfo_suffix))
+ {
+ ERR("pidl at %p is not a valid recycle bin entry",pidl);
+ return E_INVALIDARG;
+ }
+ TRASH_UnpackItemID(id,&data);
+ restore_path = wine_get_unix_file_name(data.cFileName);
+ file_path = SHAlloc(max(strlen(home_trash->files_dir),strlen(home_trash->info_dir))+strlen(filename)+1);
+ sprintf(file_path,"%s%s",home_trash->files_dir,filename);
+ file_path[strlen(home_trash->files_dir)+strlen(filename)-suffix_length] = '\0';
+ if(!rename(file_path,restore_path))
+ {
+ sprintf(file_path,"%s%s",home_trash->info_dir,filename);
+ if(unlink(file_path))
+ WARN("failed to delete the trashinfo file %s",filename);
+ }
+ else
+ WARN("could not erase %s from the trash (errno=%i)\n",filename,errno);
+ SHFree(file_path);
+ HeapFree(GetProcessHeap(), 0, restore_path);
+ return S_OK;
+}
+
HRESULT TRASH_EraseItem(LPCITEMIDLIST pidl)
{
int suffix_length = strlen(trashinfo_suffix);
diff --git a/dlls/shell32/xdg.h b/dlls/shell32/xdg.h
index 1f403ba..6236887 100644
--- a/dlls/shell32/xdg.h
+++ b/dlls/shell32/xdg.h
@@ -41,6 +41,7 @@ BOOL TRASH_CanTrashFile(LPCWSTR wszPath) DECLSPEC_HIDDEN;
BOOL TRASH_TrashFile(LPCWSTR wszPath) DECLSPEC_HIDDEN;
HRESULT TRASH_UnpackItemID(LPCSHITEMID id, WIN32_FIND_DATAW *data) DECLSPEC_HIDDEN;
HRESULT TRASH_EnumItems(LPITEMIDLIST **pidls, int *count) DECLSPEC_HIDDEN;
+HRESULT TRASH_RestoreItem(LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;
HRESULT TRASH_EraseItem(LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;
HRESULT XDG_UserDirLookup(const char * const *xdg_dirs, const unsigned int num_dirs, char *** out_ptr) DECLSPEC_HIDDEN;
More information about the wine-cvs
mailing list