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