2 * Trash virtual folder support. The trashing engine is implemented in trash.c
4 * Copyright (C) 2006 Mikolaj Zalewski
5 * Copyright 2011 Jay Yang
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define NONAMELESSUNION
38 #include "shellfolder.h"
40 #include "knownfolders.h"
41 #include "wine/debug.h"
43 #include "shell32_main.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(recyclebin
);
59 static const columninfo RecycleBinColumns
[] =
61 {IDS_SHV_COLUMN1
, &FMTID_Storage
, PID_STG_NAME
, SHCOLSTATE_TYPE_STR
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 30},
62 {IDS_SHV_COLUMN_DELFROM
, &FMTID_Displaced
, PID_DISPLACED_FROM
, SHCOLSTATE_TYPE_STR
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 30},
63 {IDS_SHV_COLUMN_DELDATE
, &FMTID_Displaced
, PID_DISPLACED_DATE
, SHCOLSTATE_TYPE_DATE
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 20},
64 {IDS_SHV_COLUMN2
, &FMTID_Storage
, PID_STG_SIZE
, SHCOLSTATE_TYPE_INT
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 20},
65 {IDS_SHV_COLUMN3
, &FMTID_Storage
, PID_STG_STORAGETYPE
,SHCOLSTATE_TYPE_INT
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 20},
66 {IDS_SHV_COLUMN4
, &FMTID_Storage
, PID_STG_WRITETIME
, SHCOLSTATE_TYPE_DATE
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 20},
67 /* {"creation time", &FMTID_Storage, PID_STG_CREATETIME, SHCOLSTATE_TYPE_DATE, LVCFMT_LEFT, 20}, */
68 /* {"attribs", &FMTID_Storage, PID_STG_ATTRIBUTES, SHCOLSTATE_TYPE_STR, LVCFMT_LEFT, 20}, */
72 #define COLUMN_DELFROM 1
73 #define COLUMN_DATEDEL 2
76 #define COLUMN_MTIME 5
78 #define COLUMNS_COUNT 6
80 static HRESULT
FormatDateTime(LPWSTR buffer
, int size
, FILETIME ft
)
86 FileTimeToLocalFileTime(&ft
, &lft
);
87 FileTimeToSystemTime(&lft
, &time
);
89 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &time
, NULL
, buffer
, size
);
90 if (ret
>0 && ret
<size
)
92 /* Append space + time without seconds */
94 GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &time
, NULL
, &buffer
[ret
], size
- ret
);
97 return (ret
!=0 ? E_FAIL
: S_OK
);
100 typedef struct tagRecycleBinMenu
102 IContextMenu2 IContextMenu2_iface
;
107 IShellFolder2
*folder
;
110 static const IContextMenu2Vtbl recycleBinMenuVtbl
;
112 static RecycleBinMenu
*impl_from_IContextMenu2(IContextMenu2
*iface
)
114 return CONTAINING_RECORD(iface
, RecycleBinMenu
, IContextMenu2_iface
);
117 static IContextMenu2
* RecycleBinMenu_Constructor(UINT cidl
, LPCITEMIDLIST
*apidl
, IShellFolder2
*folder
)
119 RecycleBinMenu
*This
= SHAlloc(sizeof(RecycleBinMenu
));
120 TRACE("(%u,%p)\n",cidl
,apidl
);
121 This
->IContextMenu2_iface
.lpVtbl
= &recycleBinMenuVtbl
;
123 This
->apidl
= _ILCopyaPidl(apidl
,cidl
);
124 IShellFolder2_AddRef(folder
);
125 This
->folder
= folder
;
127 return &This
->IContextMenu2_iface
;
130 static HRESULT WINAPI
RecycleBinMenu_QueryInterface(IContextMenu2
*iface
,
134 RecycleBinMenu
*This
= impl_from_IContextMenu2(iface
);
135 TRACE("(%p, %s, %p) - stub\n", This
, debugstr_guid(riid
), ppvObject
);
139 static ULONG WINAPI
RecycleBinMenu_AddRef(IContextMenu2
*iface
)
141 RecycleBinMenu
*This
= impl_from_IContextMenu2(iface
);
142 TRACE("(%p)\n", This
);
143 return InterlockedIncrement(&This
->refCount
);
147 static ULONG WINAPI
RecycleBinMenu_Release(IContextMenu2
*iface
)
149 RecycleBinMenu
*This
= impl_from_IContextMenu2(iface
);
151 TRACE("(%p)\n", This
);
152 result
= InterlockedDecrement(&This
->refCount
);
155 TRACE("Destroying object\n");
156 _ILFreeaPidl(This
->apidl
,This
->cidl
);
157 IShellFolder2_Release(This
->folder
);
163 static HRESULT WINAPI
RecycleBinMenu_QueryContextMenu(IContextMenu2
*iface
,
170 HMENU menures
= LoadMenuW(shell32_hInstance
,MAKEINTRESOURCEW(MENU_RECYCLEBIN
));
171 if(uFlags
& CMF_DEFAULTONLY
)
174 UINT idMax
= Shell_MergeMenus(hmenu
,GetSubMenu(menures
,0),indexMenu
,idCmdFirst
,idCmdLast
,MM_SUBMENUSHAVEIDS
);
175 TRACE("Added %d id(s)\n",idMax
-idCmdFirst
);
176 return MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
, idMax
-idCmdFirst
+1);
180 static void DoErase(RecycleBinMenu
*This
)
183 IShellFolder2_QueryInterface(This
->folder
,&IID_ISFHelper
,(void**)&helper
);
185 ISFHelper_DeleteItems(helper
,This
->cidl
,(LPCITEMIDLIST
*)This
->apidl
);
188 static void DoRestore(RecycleBinMenu
*This
)
193 for(i
=0;i
<This
->cidl
;i
++)
195 WIN32_FIND_DATAW data
;
196 TRASH_UnpackItemID(&((This
->apidl
[i
])->mkid
),&data
);
197 if(PathFileExistsW(data
.cFileName
))
199 PIDLIST_ABSOLUTE dest_pidl
= ILCreateFromPathW(data
.cFileName
);
202 if(_ILIsFolder(ILFindLastID(dest_pidl
)))
203 LoadStringW(shell32_hInstance
,IDS_RECYCLEBIN_OVERWRITEFOLDER
,
204 message
,sizeof(message
)/sizeof(WCHAR
));
206 LoadStringW(shell32_hInstance
,IDS_RECYCLEBIN_OVERWRITEFILE
,
207 message
,sizeof(message
)/sizeof(WCHAR
));
208 LoadStringW(shell32_hInstance
,IDS_RECYCLEBIN_OVERWRITE_CAPTION
,
209 caption
,sizeof(caption
)/sizeof(WCHAR
));
211 if(ShellMessageBoxW(shell32_hInstance
,GetActiveWindow(),message
,
212 caption
,MB_YESNO
|MB_ICONEXCLAMATION
,
213 data
.cFileName
)!=IDYES
)
216 if(SUCCEEDED(TRASH_RestoreItem(This
->apidl
[i
])))
218 IPersistFolder2
*persist
;
219 LPITEMIDLIST root_pidl
;
220 PIDLIST_ABSOLUTE dest_pidl
= ILCreateFromPathW(data
.cFileName
);
221 BOOL is_folder
= _ILIsFolder(ILFindLastID(dest_pidl
));
222 IShellFolder2_QueryInterface(This
->folder
,&IID_IPersistFolder2
,
224 IPersistFolder2_GetCurFolder(persist
,&root_pidl
);
225 SHChangeNotify(is_folder
? SHCNE_RMDIR
: SHCNE_DELETE
,
226 SHCNF_IDLIST
,ILCombine(root_pidl
,This
->apidl
[i
]),0);
227 SHChangeNotify(is_folder
? SHCNE_MKDIR
: SHCNE_CREATE
,
228 SHCNF_IDLIST
,dest_pidl
,0);
235 static HRESULT WINAPI
RecycleBinMenu_InvokeCommand(IContextMenu2
*iface
,
236 LPCMINVOKECOMMANDINFO pici
)
238 RecycleBinMenu
*This
= impl_from_IContextMenu2(iface
);
239 LPCSTR verb
= pici
->lpVerb
;
240 if(IS_INTRESOURCE(verb
))
244 case IDM_RECYCLEBIN_ERASE
:
247 case IDM_RECYCLEBIN_RESTORE
:
257 static HRESULT WINAPI
RecycleBinMenu_GetCommandString(IContextMenu2
*iface
,
264 TRACE("(%p, %lu, %u, %p, %s, %u) - stub\n",iface
,idCmd
,uType
,pwReserved
,debugstr_a(pszName
),cchMax
);
268 static HRESULT WINAPI
RecycleBinMenu_HandleMenuMsg(IContextMenu2
*iface
,
269 UINT uMsg
, WPARAM wParam
,
272 TRACE("(%p, %u, 0x%lx, 0x%lx) - stub\n",iface
,uMsg
,wParam
,lParam
);
277 static const IContextMenu2Vtbl recycleBinMenuVtbl
=
279 RecycleBinMenu_QueryInterface
,
280 RecycleBinMenu_AddRef
,
281 RecycleBinMenu_Release
,
282 RecycleBinMenu_QueryContextMenu
,
283 RecycleBinMenu_InvokeCommand
,
284 RecycleBinMenu_GetCommandString
,
285 RecycleBinMenu_HandleMenuMsg
,
292 typedef struct tagRecycleBin
294 IShellFolder2 IShellFolder2_iface
;
295 IPersistFolder2 IPersistFolder2_iface
;
296 ISFHelper ISFHelper_iface
;
302 static const IShellFolder2Vtbl recycleBinVtbl
;
303 static const IPersistFolder2Vtbl recycleBinPersistVtbl
;
304 static const ISFHelperVtbl sfhelperVtbl
;
306 static inline RecycleBin
*impl_from_IShellFolder2(IShellFolder2
*iface
)
308 return CONTAINING_RECORD(iface
, RecycleBin
, IShellFolder2_iface
);
311 static RecycleBin
*impl_from_IPersistFolder2(IPersistFolder2
*iface
)
313 return CONTAINING_RECORD(iface
, RecycleBin
, IPersistFolder2_iface
);
316 static RecycleBin
*impl_from_ISFHelper(ISFHelper
*iface
)
318 return CONTAINING_RECORD(iface
, RecycleBin
, ISFHelper_iface
);
321 static void RecycleBin_Destructor(RecycleBin
*This
);
323 HRESULT WINAPI
RecycleBin_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, LPVOID
*ppOutput
)
328 return CLASS_E_NOAGGREGATION
;
330 obj
= SHAlloc(sizeof(RecycleBin
));
332 return E_OUTOFMEMORY
;
333 ZeroMemory(obj
, sizeof(RecycleBin
));
334 obj
->IShellFolder2_iface
.lpVtbl
= &recycleBinVtbl
;
335 obj
->IPersistFolder2_iface
.lpVtbl
= &recycleBinPersistVtbl
;
336 obj
->ISFHelper_iface
.lpVtbl
= &sfhelperVtbl
;
337 if (FAILED(ret
= IPersistFolder2_QueryInterface(&obj
->IPersistFolder2_iface
, riid
, ppOutput
)))
339 RecycleBin_Destructor(obj
);
342 /* InterlockedIncrement(&objCount);*/
346 static void RecycleBin_Destructor(RecycleBin
*This
)
348 /* InterlockedDecrement(&objCount);*/
353 static HRESULT WINAPI
RecycleBin_QueryInterface(IShellFolder2
*iface
, REFIID riid
, void **ppvObject
)
355 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
356 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
359 if (IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_IShellFolder
)
360 || IsEqualGUID(riid
, &IID_IShellFolder2
))
361 *ppvObject
= &This
->IShellFolder2_iface
;
363 if (IsEqualGUID(riid
, &IID_IPersist
) || IsEqualGUID(riid
, &IID_IPersistFolder
)
364 || IsEqualGUID(riid
, &IID_IPersistFolder2
))
365 *ppvObject
= &This
->IPersistFolder2_iface
;
366 if (IsEqualGUID(riid
, &IID_ISFHelper
))
367 *ppvObject
= &This
->ISFHelper_iface
;
369 if (*ppvObject
!= NULL
)
371 IUnknown_AddRef((IUnknown
*)*ppvObject
);
374 WARN("no interface %s\n", debugstr_guid(riid
));
375 return E_NOINTERFACE
;
378 static ULONG WINAPI
RecycleBin_AddRef(IShellFolder2
*iface
)
380 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
381 TRACE("(%p)\n", This
);
382 return InterlockedIncrement(&This
->refCount
);
385 static ULONG WINAPI
RecycleBin_Release(IShellFolder2
*iface
)
387 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
390 TRACE("(%p)\n", This
);
391 result
= InterlockedDecrement(&This
->refCount
);
394 TRACE("Destroy object\n");
395 RecycleBin_Destructor(This
);
400 static HRESULT WINAPI
RecycleBin_ParseDisplayName(IShellFolder2
*This
, HWND hwnd
, LPBC pbc
,
401 LPOLESTR pszDisplayName
, ULONG
*pchEaten
, LPITEMIDLIST
*ppidl
,
402 ULONG
*pdwAttributes
)
408 static HRESULT WINAPI
RecycleBin_EnumObjects(IShellFolder2
*iface
, HWND hwnd
, SHCONTF grfFlags
, IEnumIDList
**ppenumIDList
)
410 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
411 IEnumIDListImpl
*list
;
413 HRESULT ret
= E_OUTOFMEMORY
;
417 TRACE("(%p, %p, %x, %p)\n", This
, hwnd
, grfFlags
, ppenumIDList
);
419 *ppenumIDList
= NULL
;
420 list
= IEnumIDList_Constructor();
422 return E_OUTOFMEMORY
;
424 if (grfFlags
& SHCONTF_NONFOLDERS
)
426 if (FAILED(ret
= TRASH_EnumItems(NULL
, &pidls
, &pidls_count
)))
428 for (i
=0; i
<pidls_count
; i
++)
429 if (!AddToEnumList(list
, pidls
[i
]))
433 *ppenumIDList
= &list
->IEnumIDList_iface
;
438 IEnumIDList_Release(&list
->IEnumIDList_iface
);
439 for (; i
<pidls_count
; i
++)
445 static HRESULT WINAPI
RecycleBin_BindToObject(IShellFolder2
*This
, LPCITEMIDLIST pidl
, LPBC pbc
, REFIID riid
, void **ppv
)
447 FIXME("(%p, %p, %p, %s, %p) - stub\n", This
, pidl
, pbc
, debugstr_guid(riid
), ppv
);
451 static HRESULT WINAPI
RecycleBin_BindToStorage(IShellFolder2
*This
, LPCITEMIDLIST pidl
, LPBC pbc
, REFIID riid
, void **ppv
)
453 FIXME("(%p, %p, %p, %s, %p) - stub\n", This
, pidl
, pbc
, debugstr_guid(riid
), ppv
);
457 static HRESULT WINAPI
RecycleBin_CompareIDs(IShellFolder2
*iface
, LPARAM lParam
, LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
459 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
463 TRACE("(%p, %p, %p, %p)\n", This
, (void *)lParam
, pidl1
, pidl2
);
464 if (pidl1
->mkid
.cb
!= pidl2
->mkid
.cb
)
465 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, pidl1
->mkid
.cb
- pidl2
->mkid
.cb
);
466 /* Looks too complicated, but in optimized memcpy we might get
467 * a 32bit wide difference and would truncate it to 16 bit, so
468 * erroneously returning equality. */
469 ret
= memcmp(pidl1
->mkid
.abID
, pidl2
->mkid
.abID
, pidl1
->mkid
.cb
);
470 if (ret
< 0) ret
= -1;
471 if (ret
> 0) ret
= 1;
472 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (unsigned short)ret
);
475 static HRESULT WINAPI
RecycleBin_CreateViewObject(IShellFolder2
*iface
, HWND hwndOwner
, REFIID riid
, void **ppv
)
477 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
479 TRACE("(%p, %p, %s, %p)\n", This
, hwndOwner
, debugstr_guid(riid
), ppv
);
482 if (IsEqualGUID(riid
, &IID_IShellView
))
487 ZeroMemory(&sfv
, sizeof(sfv
));
488 sfv
.cbSize
= sizeof(sfv
);
489 sfv
.pshf
= (IShellFolder
*)&This
->IShellFolder2_iface
;
491 TRACE("Calling SHCreateShellFolderViewEx\n");
492 ret
= SHCreateShellFolderViewEx(&sfv
, &tmp
);
493 TRACE("Result: %08x, output: %p\n", (unsigned int)ret
, tmp
);
498 return E_NOINTERFACE
;
501 static HRESULT WINAPI
RecycleBin_GetAttributesOf(IShellFolder2
*This
, UINT cidl
, LPCITEMIDLIST
*apidl
,
504 TRACE("(%p, %d, {%p, ...}, {%x})\n", This
, cidl
, apidl
[0], *rgfInOut
);
505 *rgfInOut
&= SFGAO_CANMOVE
|SFGAO_CANDELETE
|SFGAO_HASPROPSHEET
|SFGAO_FILESYSTEM
;
509 static HRESULT WINAPI
RecycleBin_GetUIObjectOf(IShellFolder2
*iface
, HWND hwndOwner
, UINT cidl
, LPCITEMIDLIST
*apidl
,
510 REFIID riid
, UINT
*rgfReserved
, void **ppv
)
512 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
514 if(IsEqualGUID(riid
, &IID_IContextMenu
) || IsEqualGUID(riid
, &IID_IContextMenu2
))
516 TRACE("(%p, %p, %d, {%p, ...}, %s, %p, %p)\n", This
, hwndOwner
, cidl
, apidl
[0], debugstr_guid(riid
), rgfReserved
, ppv
);
517 *ppv
= RecycleBinMenu_Constructor(cidl
,apidl
,&(This
->IShellFolder2_iface
));
520 FIXME("(%p, %p, %d, {%p, ...}, %s, %p, %p): stub!\n", iface
, hwndOwner
, cidl
, apidl
[0], debugstr_guid(riid
), rgfReserved
, ppv
);
525 static HRESULT WINAPI
RecycleBin_GetDisplayNameOf(IShellFolder2
*This
, LPCITEMIDLIST pidl
, SHGDNF uFlags
, STRRET
*pName
)
527 WIN32_FIND_DATAW data
;
529 TRACE("(%p, %p, %x, %p)\n", This
, pidl
, uFlags
, pName
);
530 TRASH_UnpackItemID(&pidl
->mkid
, &data
);
531 pName
->uType
= STRRET_WSTR
;
532 return SHStrDupW(PathFindFileNameW(data
.cFileName
), &pName
->u
.pOleStr
);
535 static HRESULT WINAPI
RecycleBin_SetNameOf(IShellFolder2
*This
, HWND hwnd
, LPCITEMIDLIST pidl
, LPCOLESTR pszName
,
536 SHGDNF uFlags
, LPITEMIDLIST
*ppidlOut
)
539 return E_FAIL
; /* not supported */
542 static HRESULT WINAPI
RecycleBin_GetClassID(IPersistFolder2
*This
, CLSID
*pClassID
)
544 TRACE("(%p, %p)\n", This
, pClassID
);
545 if (This
== NULL
|| pClassID
== NULL
)
547 *pClassID
= CLSID_RecycleBin
;
551 static HRESULT WINAPI
RecycleBin_Initialize(IPersistFolder2
*iface
, LPCITEMIDLIST pidl
)
553 RecycleBin
*This
= impl_from_IPersistFolder2(iface
);
554 TRACE("(%p, %p)\n", This
, pidl
);
556 This
->pidl
= ILClone(pidl
);
557 if (This
->pidl
== NULL
)
558 return E_OUTOFMEMORY
;
562 static HRESULT WINAPI
RecycleBin_GetCurFolder(IPersistFolder2
*iface
, LPITEMIDLIST
*ppidl
)
564 RecycleBin
*This
= impl_from_IPersistFolder2(iface
);
566 *ppidl
= ILClone(This
->pidl
);
570 static HRESULT WINAPI
RecycleBin_GetDefaultSearchGUID(IShellFolder2
*iface
, GUID
*guid
)
572 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
573 TRACE("(%p)->(%p)\n", This
, guid
);
577 static HRESULT WINAPI
RecycleBin_EnumSearches(IShellFolder2
*iface
, IEnumExtraSearch
**ppEnum
)
584 static HRESULT WINAPI
RecycleBin_GetDefaultColumn(IShellFolder2
*iface
, DWORD reserved
, ULONG
*sort
, ULONG
*display
)
586 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
588 TRACE("(%p)->(%#x, %p, %p)\n", This
, reserved
, sort
, display
);
593 static HRESULT WINAPI
RecycleBin_GetDefaultColumnState(IShellFolder2
*iface
, UINT iColumn
, SHCOLSTATEF
*pcsFlags
)
595 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
596 TRACE("(%p, %d, %p)\n", This
, iColumn
, pcsFlags
);
597 if (iColumn
>= COLUMNS_COUNT
)
599 *pcsFlags
= RecycleBinColumns
[iColumn
].pcsFlags
;
603 static HRESULT WINAPI
RecycleBin_GetDetailsEx(IShellFolder2
*iface
, LPCITEMIDLIST pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
609 static HRESULT WINAPI
RecycleBin_GetDetailsOf(IShellFolder2
*iface
, LPCITEMIDLIST pidl
, UINT iColumn
, LPSHELLDETAILS pDetails
)
611 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
612 WIN32_FIND_DATAW data
;
613 WCHAR buffer
[MAX_PATH
];
615 TRACE("(%p, %p, %d, %p)\n", This
, pidl
, iColumn
, pDetails
);
616 if (iColumn
>= COLUMNS_COUNT
)
618 pDetails
->fmt
= RecycleBinColumns
[iColumn
].fmt
;
619 pDetails
->cxChar
= RecycleBinColumns
[iColumn
].cxChars
;
622 pDetails
->str
.uType
= STRRET_WSTR
;
623 LoadStringW(shell32_hInstance
, RecycleBinColumns
[iColumn
].column_name_id
, buffer
, MAX_PATH
);
624 return SHStrDupW(buffer
, &pDetails
->str
.u
.pOleStr
);
627 if (iColumn
== COLUMN_NAME
)
628 return RecycleBin_GetDisplayNameOf(iface
, pidl
, SHGDN_NORMAL
, &pDetails
->str
);
630 TRASH_UnpackItemID(&pidl
->mkid
, &data
);
634 FormatDateTime(buffer
, MAX_PATH
, data
.ftLastAccessTime
);
637 lstrcpyW(buffer
, data
.cFileName
);
638 PathRemoveFileSpecW(buffer
);
641 StrFormatKBSizeW(((LONGLONG
)data
.nFileSizeHigh
<<32)|data
.nFileSizeLow
, buffer
, MAX_PATH
);
644 FormatDateTime(buffer
, MAX_PATH
, data
.ftLastWriteTime
);
654 pDetails
->str
.uType
= STRRET_WSTR
;
655 return SHStrDupW(buffer
, &pDetails
->str
.u
.pOleStr
);
658 static HRESULT WINAPI
RecycleBin_MapColumnToSCID(IShellFolder2
*iface
, UINT iColumn
, SHCOLUMNID
*pscid
)
660 RecycleBin
*This
= impl_from_IShellFolder2(iface
);
661 TRACE("(%p, %d, %p)\n", This
, iColumn
, pscid
);
662 if (iColumn
>=COLUMNS_COUNT
)
664 pscid
->fmtid
= *RecycleBinColumns
[iColumn
].fmtId
;
665 pscid
->pid
= RecycleBinColumns
[iColumn
].pid
;
669 static const IShellFolder2Vtbl recycleBinVtbl
=
672 RecycleBin_QueryInterface
,
677 RecycleBin_ParseDisplayName
,
678 RecycleBin_EnumObjects
,
679 RecycleBin_BindToObject
,
680 RecycleBin_BindToStorage
,
681 RecycleBin_CompareIDs
,
682 RecycleBin_CreateViewObject
,
683 RecycleBin_GetAttributesOf
,
684 RecycleBin_GetUIObjectOf
,
685 RecycleBin_GetDisplayNameOf
,
686 RecycleBin_SetNameOf
,
689 RecycleBin_GetDefaultSearchGUID
,
690 RecycleBin_EnumSearches
,
691 RecycleBin_GetDefaultColumn
,
692 RecycleBin_GetDefaultColumnState
,
693 RecycleBin_GetDetailsEx
,
694 RecycleBin_GetDetailsOf
,
695 RecycleBin_MapColumnToSCID
698 static HRESULT WINAPI
RecycleBin_IPersistFolder2_QueryInterface(IPersistFolder2
*iface
, REFIID riid
,
701 RecycleBin
*This
= impl_from_IPersistFolder2(iface
);
703 return IShellFolder2_QueryInterface(&This
->IShellFolder2_iface
, riid
, ppvObject
);
706 static ULONG WINAPI
RecycleBin_IPersistFolder2_AddRef(IPersistFolder2
*iface
)
708 RecycleBin
*This
= impl_from_IPersistFolder2(iface
);
710 return IShellFolder2_AddRef(&This
->IShellFolder2_iface
);
713 static ULONG WINAPI
RecycleBin_IPersistFolder2_Release(IPersistFolder2
*iface
)
715 RecycleBin
*This
= impl_from_IPersistFolder2(iface
);
717 return IShellFolder2_Release(&This
->IShellFolder2_iface
);
720 static const IPersistFolder2Vtbl recycleBinPersistVtbl
=
723 RecycleBin_IPersistFolder2_QueryInterface
,
724 RecycleBin_IPersistFolder2_AddRef
,
725 RecycleBin_IPersistFolder2_Release
,
728 RecycleBin_GetClassID
,
730 RecycleBin_Initialize
,
731 /* IPersistFolder2 */
732 RecycleBin_GetCurFolder
735 static HRESULT WINAPI
RecycleBin_ISFHelper_QueryInterface(ISFHelper
*iface
, REFIID riid
,
738 RecycleBin
*This
= impl_from_ISFHelper(iface
);
740 return IShellFolder2_QueryInterface(&This
->IShellFolder2_iface
, riid
, ppvObject
);
743 static ULONG WINAPI
RecycleBin_ISFHelper_AddRef(ISFHelper
*iface
)
745 RecycleBin
*This
= impl_from_ISFHelper(iface
);
747 return IShellFolder2_AddRef(&This
->IShellFolder2_iface
);
750 static ULONG WINAPI
RecycleBin_ISFHelper_Release(ISFHelper
*iface
)
752 RecycleBin
*This
= impl_from_ISFHelper(iface
);
754 return IShellFolder2_Release(&This
->IShellFolder2_iface
);
757 static HRESULT WINAPI
RecycleBin_GetUniqueName(ISFHelper
*iface
,LPWSTR lpName
,
763 static HRESULT WINAPI
RecycleBin_AddFolder(ISFHelper
* iface
, HWND hwnd
,
765 LPITEMIDLIST
* ppidlOut
)
767 /*Adding folders doesn't make sense in the recycle bin*/
771 static HRESULT
erase_items(HWND parent
,const LPCITEMIDLIST
* apidl
, UINT cidl
, BOOL confirm
)
775 LPITEMIDLIST recyclebin
;
788 WIN32_FIND_DATAW data
;
789 TRASH_UnpackItemID(&((*apidl
)->mkid
),&data
);
790 lstrcpynW(arg
,data
.cFileName
,MAX_PATH
);
791 LoadStringW(shell32_hInstance
,IDS_RECYCLEBIN_ERASEITEM
,message
,
792 sizeof(message
)/sizeof(WCHAR
));
797 static const WCHAR format
[]={'%','u','\0'};
798 LoadStringW(shell32_hInstance
,IDS_RECYCLEBIN_ERASEMULTIPLE
,
799 message
,sizeof(message
)/sizeof(WCHAR
));
800 sprintfW(arg
,format
,cidl
);
805 LoadStringW(shell32_hInstance
,IDS_RECYCLEBIN_ERASE_CAPTION
,caption
,
806 sizeof(caption
)/sizeof(WCHAR
));
807 if(ShellMessageBoxW(shell32_hInstance
,parent
,message
,caption
,
808 MB_YESNO
|MB_ICONEXCLAMATION
,arg
)!=IDYES
)
812 SHGetFolderLocation(parent
,CSIDL_BITBUCKET
,0,0,&recyclebin
);
815 if(SUCCEEDED(TRASH_EraseItem(apidl
[i
])))
816 SHChangeNotify(SHCNE_DELETE
,SHCNF_IDLIST
,
817 ILCombine(recyclebin
,apidl
[i
]),0);
823 static HRESULT WINAPI
RecycleBin_DeleteItems(ISFHelper
* iface
, UINT cidl
,
824 LPCITEMIDLIST
* apidl
)
826 TRACE("(%p,%u,%p)\n",iface
,cidl
,apidl
);
827 return erase_items(GetActiveWindow(),apidl
,cidl
,TRUE
);
830 static HRESULT WINAPI
RecycleBin_CopyItems(ISFHelper
* iface
,
831 IShellFolder
* pSFFrom
,
832 UINT cidl
, LPCITEMIDLIST
* apidl
)
837 static const ISFHelperVtbl sfhelperVtbl
=
839 RecycleBin_ISFHelper_QueryInterface
,
840 RecycleBin_ISFHelper_AddRef
,
841 RecycleBin_ISFHelper_Release
,
842 RecycleBin_GetUniqueName
,
843 RecycleBin_AddFolder
,
844 RecycleBin_DeleteItems
,
848 HRESULT WINAPI
SHQueryRecycleBinA(LPCSTR pszRootPath
, LPSHQUERYRBINFO pSHQueryRBInfo
)
850 WCHAR wszRootPath
[MAX_PATH
];
851 MultiByteToWideChar(CP_ACP
, 0, pszRootPath
, -1, wszRootPath
, MAX_PATH
);
852 return SHQueryRecycleBinW(wszRootPath
, pSHQueryRBInfo
);
855 HRESULT WINAPI
SHQueryRecycleBinW(LPCWSTR pszRootPath
, LPSHQUERYRBINFO pSHQueryRBInfo
)
862 TRACE("(%s, %p)\n", debugstr_w(pszRootPath
), pSHQueryRBInfo
);
864 hr
= TRASH_EnumItems(pszRootPath
, &apidl
, &cidl
);
867 pSHQueryRBInfo
->i64NumItems
= cidl
;
868 pSHQueryRBInfo
->i64Size
= 0;
871 WIN32_FIND_DATAW data
;
872 TRASH_UnpackItemID(&((apidl
[i
])->mkid
),&data
);
873 pSHQueryRBInfo
->i64Size
+= ((DWORDLONG
)data
.nFileSizeHigh
<< 32) + data
.nFileSizeLow
;
880 HRESULT WINAPI
SHEmptyRecycleBinA(HWND hwnd
, LPCSTR pszRootPath
, DWORD dwFlags
)
882 WCHAR wszRootPath
[MAX_PATH
];
883 MultiByteToWideChar(CP_ACP
, 0, pszRootPath
, -1, wszRootPath
, MAX_PATH
);
884 return SHEmptyRecycleBinW(hwnd
, wszRootPath
, dwFlags
);
887 #define SHERB_NOCONFIRMATION 1
888 #define SHERB_NOPROGRESSUI 2
889 #define SHERB_NOSOUND 4
891 HRESULT WINAPI
SHEmptyRecycleBinW(HWND hwnd
, LPCWSTR pszRootPath
, DWORD dwFlags
)
898 TRACE("(%p, %s, 0x%08x)\n", hwnd
, debugstr_w(pszRootPath
) , dwFlags
);
900 ret
= TRASH_EnumItems(pszRootPath
, &apidl
, &cidl
);
904 ret
= erase_items(hwnd
,(const LPCITEMIDLIST
*)apidl
,cidl
,!(dwFlags
& SHERB_NOCONFIRMATION
));
911 /*************************************************************************
912 * SHUpdateRecycleBinIcon [SHELL32.@]
916 HRESULT WINAPI
SHUpdateRecycleBinIcon(void)