From 80c62ca20349582e339fbc398be35b9a8cff6d01 Mon Sep 17 00:00:00 2001 From: Jay Yang Date: Fri, 8 Jul 2011 10:47:08 -0400 Subject: [PATCH] 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(+) diff --git a/dlls/shell32/recyclebin.c b/dlls/shell32/recyclebin.c index a98bc090713..f840bf15473 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;icidl;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 c449dce14b1..c64e203a069 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 1f403ba5edb..62368874df8 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;