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)\n",pidl); if(strcmp(filename+strlen(filename)-suffix_length,trashinfo_suffix)) { ERR("pidl at %p is not a valid recycle bin entry\n",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\n",filename); } else WARN("could not erase %s from the trash (errno=%i)\n",filename,errno); SHFree(file_path); heap_free(restore_path); return S_OK; }
static HRESULT WINAPI RecycleBin_GetDisplayNameOf(IShellFolder2 *This, LPCITEMIDLIST pidl, SHGDNF uFlags, STRRET *pName) { WIN32_FIND_DATAW data; TRACE("(%p, %p, %x, %p)\n", This, pidl, uFlags, pName); TRASH_UnpackItemID(&pidl->mkid, &data); pName->uType = STRRET_WSTR; pName->u.pOleStr = StrDupW(PathFindFileNameW(data.cFileName)); if (pName->u.pOleStr == NULL) return E_OUTOFMEMORY; return S_OK; }
static HRESULT erase_items(HWND parent,const LPCITEMIDLIST * apidl, UINT cidl, BOOL confirm) { UINT i=0; HRESULT ret = S_OK; LPITEMIDLIST recyclebin; if(confirm) { WCHAR arg[MAX_PATH]; WCHAR message[100]; WCHAR caption[50]; switch(cidl) { case 0: return S_OK; case 1: { WIN32_FIND_DATAW data; TRASH_UnpackItemID(&((*apidl)->mkid),&data); lstrcpynW(arg,data.cFileName,MAX_PATH); LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_ERASEITEM,message, sizeof(message)/sizeof(WCHAR)); break; } default: { static const WCHAR format[]={'%','u','\0'}; LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_ERASEMULTIPLE, message,sizeof(message)/sizeof(WCHAR)); sprintfW(arg,format,cidl); break; } } LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_ERASE_CAPTION,caption, sizeof(caption)/sizeof(WCHAR)); if(ShellMessageBoxW(shell32_hInstance,parent,message,caption, MB_YESNO|MB_ICONEXCLAMATION,arg)!=IDYES) return ret; } SHGetFolderLocation(parent,CSIDL_BITBUCKET,0,0,&recyclebin); for (; i<cidl; i++) { if(SUCCEEDED(TRASH_EraseItem(apidl[i]))) SHChangeNotify(SHCNE_DELETE,SHCNF_IDLIST, ILCombine(recyclebin,apidl[i]),0); } ILFree(recyclebin); return S_OK; }
static HRESULT WINAPI RecycleBin_GetDetailsOf(IShellFolder2 *iface, LPCITEMIDLIST pidl, UINT iColumn, LPSHELLDETAILS pDetails) { RecycleBin *This = impl_from_IShellFolder2(iface); WIN32_FIND_DATAW data; WCHAR buffer[MAX_PATH]; TRACE("(%p, %p, %d, %p)\n", This, pidl, iColumn, pDetails); if (iColumn >= COLUMNS_COUNT) return E_FAIL; pDetails->fmt = RecycleBinColumns[iColumn].fmt; pDetails->cxChar = RecycleBinColumns[iColumn].cxChars; if (pidl == NULL) { pDetails->str.uType = STRRET_WSTR; LoadStringW(shell32_hInstance, RecycleBinColumns[iColumn].column_name_id, buffer, MAX_PATH); return SHStrDupW(buffer, &pDetails->str.u.pOleStr); } if (iColumn == COLUMN_NAME) return RecycleBin_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL, &pDetails->str); TRASH_UnpackItemID(&pidl->mkid, &data); switch (iColumn) { case COLUMN_DATEDEL: FormatDateTime(buffer, MAX_PATH, data.ftLastAccessTime); break; case COLUMN_DELFROM: lstrcpyW(buffer, data.cFileName); PathRemoveFileSpecW(buffer); break; case COLUMN_SIZE: StrFormatKBSizeW(((LONGLONG)data.nFileSizeHigh<<32)|data.nFileSizeLow, buffer, MAX_PATH); break; case COLUMN_MTIME: FormatDateTime(buffer, MAX_PATH, data.ftLastWriteTime); break; case COLUMN_TYPE: /* TODO */ buffer[0] = 0; break; default: return E_FAIL; } pDetails->str.uType = STRRET_WSTR; return SHStrDupW(buffer, &pDetails->str.u.pOleStr); }
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); } } }
HRESULT WINAPI SHQueryRecycleBinW(LPCWSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo) { LPITEMIDLIST *apidl; INT cidl; INT i=0; TRACE("(%s, %p)\n", debugstr_w(pszRootPath), pSHQueryRBInfo); FIXME("Ignoring pszRootPath=%s\n",debugstr_w(pszRootPath)); TRASH_EnumItems(&apidl,&cidl); pSHQueryRBInfo->i64NumItems = cidl; pSHQueryRBInfo->i64Size = 0; for (; i<cidl; i++) { WIN32_FIND_DATAW data; TRASH_UnpackItemID(&((apidl[i])->mkid),&data); pSHQueryRBInfo->i64Size += ((DWORDLONG)data.nFileSizeHigh << 32) + data.nFileSizeLow; ILFree(apidl[i]); } SHFree(apidl); return S_OK; }