webservices: Add a stub implementation of WS_TYPE_ATTRIBUTE_FIELD_MAPPING in the...
[wine.git] / dlls / shell32 / recyclebin.c
blob80e5aad430043b0511bdbed54b2f8345f65df823
1 /*
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
22 #include "config.h"
24 #define COBJMACROS
25 #define NONAMELESSUNION
27 #include <stdarg.h>
29 #include "winerror.h"
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winreg.h"
33 #include "winuser.h"
34 #include "shlwapi.h"
35 #include "ntquery.h"
36 #include "shlobj.h"
37 #include "shresdef.h"
38 #include "shellfolder.h"
39 #include "shellapi.h"
40 #include "knownfolders.h"
41 #include "wine/debug.h"
43 #include "shell32_main.h"
44 #include "xdg.h"
45 #include "pidl.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(recyclebin);
49 typedef struct
51 int column_name_id;
52 const GUID *fmtId;
53 DWORD pid;
54 int pcsFlags;
55 int fmt;
56 int cxChars;
57 } columninfo;
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}, */
71 #define COLUMN_NAME 0
72 #define COLUMN_DELFROM 1
73 #define COLUMN_DATEDEL 2
74 #define COLUMN_SIZE 3
75 #define COLUMN_TYPE 4
76 #define COLUMN_MTIME 5
78 #define COLUMNS_COUNT 6
80 static HRESULT FormatDateTime(LPWSTR buffer, int size, FILETIME ft)
82 FILETIME lft;
83 SYSTEMTIME time;
84 int ret;
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 */
93 buffer[ret-1] = ' ';
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;
103 LONG refCount;
105 UINT cidl;
106 LPITEMIDLIST *apidl;
107 IShellFolder2 *folder;
108 } RecycleBinMenu;
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;
122 This->cidl = cidl;
123 This->apidl = _ILCopyaPidl(apidl,cidl);
124 IShellFolder2_AddRef(folder);
125 This->folder = folder;
126 This->refCount = 1;
127 return &This->IContextMenu2_iface;
130 static HRESULT WINAPI RecycleBinMenu_QueryInterface(IContextMenu2 *iface,
131 REFIID riid,
132 void **ppvObject)
134 RecycleBinMenu *This = impl_from_IContextMenu2(iface);
135 TRACE("(%p, %s, %p) - stub\n", This, debugstr_guid(riid), ppvObject);
136 return E_NOTIMPL;
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);
150 UINT result;
151 TRACE("(%p)\n", This);
152 result = InterlockedDecrement(&This->refCount);
153 if (result == 0)
155 TRACE("Destroying object\n");
156 _ILFreeaPidl(This->apidl,This->cidl);
157 IShellFolder2_Release(This->folder);
158 SHFree(This);
160 return result;
163 static HRESULT WINAPI RecycleBinMenu_QueryContextMenu(IContextMenu2 *iface,
164 HMENU hmenu,
165 UINT indexMenu,
166 UINT idCmdFirst,
167 UINT idCmdLast,
168 UINT uFlags)
170 HMENU menures = LoadMenuW(shell32_hInstance,MAKEINTRESOURCEW(MENU_RECYCLEBIN));
171 if(uFlags & CMF_DEFAULTONLY)
172 return E_NOTIMPL;
173 else{
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)
182 ISFHelper *helper;
183 IShellFolder2_QueryInterface(This->folder,&IID_ISFHelper,(void**)&helper);
184 if(helper)
185 ISFHelper_DeleteItems(helper,This->cidl,(LPCITEMIDLIST*)This->apidl);
188 static void DoRestore(RecycleBinMenu *This)
191 /*TODO add prompts*/
192 UINT i;
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);
200 WCHAR message[100];
201 WCHAR caption[50];
202 if(_ILIsFolder(ILFindLastID(dest_pidl)))
203 LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_OVERWRITEFOLDER,
204 message,sizeof(message)/sizeof(WCHAR));
205 else
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)
214 continue;
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,
223 (void**)&persist);
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);
229 ILFree(dest_pidl);
230 ILFree(root_pidl);
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))
242 switch(LOWORD(verb))
244 case IDM_RECYCLEBIN_ERASE:
245 DoErase(This);
246 break;
247 case IDM_RECYCLEBIN_RESTORE:
248 DoRestore(This);
249 break;
250 default:
251 return E_NOTIMPL;
254 return S_OK;
257 static HRESULT WINAPI RecycleBinMenu_GetCommandString(IContextMenu2 *iface,
258 UINT_PTR idCmd,
259 UINT uType,
260 UINT *pwReserved,
261 LPSTR pszName,
262 UINT cchMax)
264 TRACE("(%p, %lu, %u, %p, %s, %u) - stub\n",iface,idCmd,uType,pwReserved,debugstr_a(pszName),cchMax);
265 return E_NOTIMPL;
268 static HRESULT WINAPI RecycleBinMenu_HandleMenuMsg(IContextMenu2 *iface,
269 UINT uMsg, WPARAM wParam,
270 LPARAM lParam)
272 TRACE("(%p, %u, 0x%lx, 0x%lx) - stub\n",iface,uMsg,wParam,lParam);
273 return E_NOTIMPL;
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,
289 * Recycle Bin folder
292 typedef struct tagRecycleBin
294 IShellFolder2 IShellFolder2_iface;
295 IPersistFolder2 IPersistFolder2_iface;
296 ISFHelper ISFHelper_iface;
297 LONG refCount;
299 LPITEMIDLIST pidl;
300 } RecycleBin;
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)
325 RecycleBin *obj;
326 HRESULT ret;
327 if (pUnkOuter)
328 return CLASS_E_NOAGGREGATION;
330 obj = SHAlloc(sizeof(RecycleBin));
331 if (obj == NULL)
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);
340 return ret;
342 /* InterlockedIncrement(&objCount);*/
343 return S_OK;
346 static void RecycleBin_Destructor(RecycleBin *This)
348 /* InterlockedDecrement(&objCount);*/
349 SHFree(This->pidl);
350 SHFree(This);
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);
358 *ppvObject = NULL;
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);
372 return S_OK;
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);
388 LONG result;
390 TRACE("(%p)\n", This);
391 result = InterlockedDecrement(&This->refCount);
392 if (result == 0)
394 TRACE("Destroy object\n");
395 RecycleBin_Destructor(This);
397 return result;
400 static HRESULT WINAPI RecycleBin_ParseDisplayName(IShellFolder2 *This, HWND hwnd, LPBC pbc,
401 LPOLESTR pszDisplayName, ULONG *pchEaten, LPITEMIDLIST *ppidl,
402 ULONG *pdwAttributes)
404 FIXME("stub\n");
405 return E_NOTIMPL;
408 static HRESULT WINAPI RecycleBin_EnumObjects(IShellFolder2 *iface, HWND hwnd, SHCONTF grfFlags, IEnumIDList **ppenumIDList)
410 RecycleBin *This = impl_from_IShellFolder2(iface);
411 IEnumIDListImpl *list;
412 LPITEMIDLIST *pidls;
413 HRESULT ret = E_OUTOFMEMORY;
414 int pidls_count = 0;
415 int i=0;
417 TRACE("(%p, %p, %x, %p)\n", This, hwnd, grfFlags, ppenumIDList);
419 *ppenumIDList = NULL;
420 list = IEnumIDList_Constructor();
421 if (!list)
422 return E_OUTOFMEMORY;
424 if (grfFlags & SHCONTF_NONFOLDERS)
426 if (FAILED(ret = TRASH_EnumItems(NULL, &pidls, &pidls_count)))
427 goto failed;
428 for (i=0; i<pidls_count; i++)
429 if (!AddToEnumList(list, pidls[i]))
430 goto failed;
433 *ppenumIDList = &list->IEnumIDList_iface;
434 return S_OK;
436 failed:
437 if (list)
438 IEnumIDList_Release(&list->IEnumIDList_iface);
439 for (; i<pidls_count; i++)
440 ILFree(pidls[i]);
441 SHFree(pidls);
442 return ret;
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);
448 return E_NOTIMPL;
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);
454 return E_NOTIMPL;
457 static HRESULT WINAPI RecycleBin_CompareIDs(IShellFolder2 *iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
459 RecycleBin *This = impl_from_IShellFolder2(iface);
460 int ret;
462 /* TODO */
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);
478 HRESULT ret;
479 TRACE("(%p, %p, %s, %p)\n", This, hwndOwner, debugstr_guid(riid), ppv);
481 *ppv = NULL;
482 if (IsEqualGUID(riid, &IID_IShellView))
484 IShellView *tmp;
485 CSFV sfv;
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);
494 *ppv = tmp;
495 return ret;
498 return E_NOINTERFACE;
501 static HRESULT WINAPI RecycleBin_GetAttributesOf(IShellFolder2 *This, UINT cidl, LPCITEMIDLIST *apidl,
502 SFGAOF *rgfInOut)
504 TRACE("(%p, %d, {%p, ...}, {%x})\n", This, cidl, apidl[0], *rgfInOut);
505 *rgfInOut &= SFGAO_CANMOVE|SFGAO_CANDELETE|SFGAO_HASPROPSHEET|SFGAO_FILESYSTEM;
506 return S_OK;
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);
513 *ppv = NULL;
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));
518 return S_OK;
520 FIXME("(%p, %p, %d, {%p, ...}, %s, %p, %p): stub!\n", iface, hwndOwner, cidl, apidl[0], debugstr_guid(riid), rgfReserved, ppv);
522 return E_NOTIMPL;
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)
538 TRACE("\n");
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)
546 return E_INVALIDARG;
547 *pClassID = CLSID_RecycleBin;
548 return S_OK;
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;
559 return S_OK;
562 static HRESULT WINAPI RecycleBin_GetCurFolder(IPersistFolder2 *iface, LPITEMIDLIST *ppidl)
564 RecycleBin *This = impl_from_IPersistFolder2(iface);
565 TRACE("\n");
566 *ppidl = ILClone(This->pidl);
567 return S_OK;
570 static HRESULT WINAPI RecycleBin_GetDefaultSearchGUID(IShellFolder2 *iface, GUID *pguid)
572 FIXME("stub\n");
573 return E_NOTIMPL;
576 static HRESULT WINAPI RecycleBin_EnumSearches(IShellFolder2 *iface, IEnumExtraSearch **ppEnum)
578 FIXME("stub\n");
579 *ppEnum = NULL;
580 return E_NOTIMPL;
583 static HRESULT WINAPI RecycleBin_GetDefaultColumn(IShellFolder2 *iface, DWORD dwReserved, ULONG *pSort, ULONG *pDisplay)
585 RecycleBin *This = impl_from_IShellFolder2(iface);
586 TRACE("(%p, %x, %p, %p)\n", This, dwReserved, pSort, pDisplay);
587 *pSort = 0;
588 *pDisplay = 0;
589 return S_OK;
592 static HRESULT WINAPI RecycleBin_GetDefaultColumnState(IShellFolder2 *iface, UINT iColumn, SHCOLSTATEF *pcsFlags)
594 RecycleBin *This = impl_from_IShellFolder2(iface);
595 TRACE("(%p, %d, %p)\n", This, iColumn, pcsFlags);
596 if (iColumn >= COLUMNS_COUNT)
597 return E_INVALIDARG;
598 *pcsFlags = RecycleBinColumns[iColumn].pcsFlags;
599 return S_OK;
602 static HRESULT WINAPI RecycleBin_GetDetailsEx(IShellFolder2 *iface, LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
604 FIXME("stub\n");
605 return E_NOTIMPL;
608 static HRESULT WINAPI RecycleBin_GetDetailsOf(IShellFolder2 *iface, LPCITEMIDLIST pidl, UINT iColumn, LPSHELLDETAILS pDetails)
610 RecycleBin *This = impl_from_IShellFolder2(iface);
611 WIN32_FIND_DATAW data;
612 WCHAR buffer[MAX_PATH];
614 TRACE("(%p, %p, %d, %p)\n", This, pidl, iColumn, pDetails);
615 if (iColumn >= COLUMNS_COUNT)
616 return E_FAIL;
617 pDetails->fmt = RecycleBinColumns[iColumn].fmt;
618 pDetails->cxChar = RecycleBinColumns[iColumn].cxChars;
619 if (pidl == NULL)
621 pDetails->str.uType = STRRET_WSTR;
622 LoadStringW(shell32_hInstance, RecycleBinColumns[iColumn].column_name_id, buffer, MAX_PATH);
623 return SHStrDupW(buffer, &pDetails->str.u.pOleStr);
626 if (iColumn == COLUMN_NAME)
627 return RecycleBin_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL, &pDetails->str);
629 TRASH_UnpackItemID(&pidl->mkid, &data);
630 switch (iColumn)
632 case COLUMN_DATEDEL:
633 FormatDateTime(buffer, MAX_PATH, data.ftLastAccessTime);
634 break;
635 case COLUMN_DELFROM:
636 lstrcpyW(buffer, data.cFileName);
637 PathRemoveFileSpecW(buffer);
638 break;
639 case COLUMN_SIZE:
640 StrFormatKBSizeW(((LONGLONG)data.nFileSizeHigh<<32)|data.nFileSizeLow, buffer, MAX_PATH);
641 break;
642 case COLUMN_MTIME:
643 FormatDateTime(buffer, MAX_PATH, data.ftLastWriteTime);
644 break;
645 case COLUMN_TYPE:
646 /* TODO */
647 buffer[0] = 0;
648 break;
649 default:
650 return E_FAIL;
653 pDetails->str.uType = STRRET_WSTR;
654 return SHStrDupW(buffer, &pDetails->str.u.pOleStr);
657 static HRESULT WINAPI RecycleBin_MapColumnToSCID(IShellFolder2 *iface, UINT iColumn, SHCOLUMNID *pscid)
659 RecycleBin *This = impl_from_IShellFolder2(iface);
660 TRACE("(%p, %d, %p)\n", This, iColumn, pscid);
661 if (iColumn>=COLUMNS_COUNT)
662 return E_INVALIDARG;
663 pscid->fmtid = *RecycleBinColumns[iColumn].fmtId;
664 pscid->pid = RecycleBinColumns[iColumn].pid;
665 return S_OK;
668 static const IShellFolder2Vtbl recycleBinVtbl =
670 /* IUnknown */
671 RecycleBin_QueryInterface,
672 RecycleBin_AddRef,
673 RecycleBin_Release,
675 /* IShellFolder */
676 RecycleBin_ParseDisplayName,
677 RecycleBin_EnumObjects,
678 RecycleBin_BindToObject,
679 RecycleBin_BindToStorage,
680 RecycleBin_CompareIDs,
681 RecycleBin_CreateViewObject,
682 RecycleBin_GetAttributesOf,
683 RecycleBin_GetUIObjectOf,
684 RecycleBin_GetDisplayNameOf,
685 RecycleBin_SetNameOf,
687 /* IShellFolder2 */
688 RecycleBin_GetDefaultSearchGUID,
689 RecycleBin_EnumSearches,
690 RecycleBin_GetDefaultColumn,
691 RecycleBin_GetDefaultColumnState,
692 RecycleBin_GetDetailsEx,
693 RecycleBin_GetDetailsOf,
694 RecycleBin_MapColumnToSCID
697 static HRESULT WINAPI RecycleBin_IPersistFolder2_QueryInterface(IPersistFolder2 *iface, REFIID riid,
698 void **ppvObject)
700 RecycleBin *This = impl_from_IPersistFolder2(iface);
702 return IShellFolder2_QueryInterface(&This->IShellFolder2_iface, riid, ppvObject);
705 static ULONG WINAPI RecycleBin_IPersistFolder2_AddRef(IPersistFolder2 *iface)
707 RecycleBin *This = impl_from_IPersistFolder2(iface);
709 return IShellFolder2_AddRef(&This->IShellFolder2_iface);
712 static ULONG WINAPI RecycleBin_IPersistFolder2_Release(IPersistFolder2 *iface)
714 RecycleBin *This = impl_from_IPersistFolder2(iface);
716 return IShellFolder2_Release(&This->IShellFolder2_iface);
719 static const IPersistFolder2Vtbl recycleBinPersistVtbl =
721 /* IUnknown */
722 RecycleBin_IPersistFolder2_QueryInterface,
723 RecycleBin_IPersistFolder2_AddRef,
724 RecycleBin_IPersistFolder2_Release,
726 /* IPersist */
727 RecycleBin_GetClassID,
728 /* IPersistFolder */
729 RecycleBin_Initialize,
730 /* IPersistFolder2 */
731 RecycleBin_GetCurFolder
734 static HRESULT WINAPI RecycleBin_ISFHelper_QueryInterface(ISFHelper *iface, REFIID riid,
735 void **ppvObject)
737 RecycleBin *This = impl_from_ISFHelper(iface);
739 return IShellFolder2_QueryInterface(&This->IShellFolder2_iface, riid, ppvObject);
742 static ULONG WINAPI RecycleBin_ISFHelper_AddRef(ISFHelper *iface)
744 RecycleBin *This = impl_from_ISFHelper(iface);
746 return IShellFolder2_AddRef(&This->IShellFolder2_iface);
749 static ULONG WINAPI RecycleBin_ISFHelper_Release(ISFHelper *iface)
751 RecycleBin *This = impl_from_ISFHelper(iface);
753 return IShellFolder2_Release(&This->IShellFolder2_iface);
756 static HRESULT WINAPI RecycleBin_GetUniqueName(ISFHelper *iface,LPWSTR lpName,
757 UINT uLen)
759 return E_NOTIMPL;
762 static HRESULT WINAPI RecycleBin_AddFolder(ISFHelper * iface, HWND hwnd,
763 LPCWSTR pwszName,
764 LPITEMIDLIST * ppidlOut)
766 /*Adding folders doesn't make sense in the recycle bin*/
767 return E_NOTIMPL;
770 static HRESULT erase_items(HWND parent,const LPCITEMIDLIST * apidl, UINT cidl, BOOL confirm)
772 UINT i=0;
773 HRESULT ret = S_OK;
774 LPITEMIDLIST recyclebin;
776 if(confirm)
778 WCHAR arg[MAX_PATH];
779 WCHAR message[100];
780 WCHAR caption[50];
781 switch(cidl)
783 case 0:
784 return S_OK;
785 case 1:
787 WIN32_FIND_DATAW data;
788 TRASH_UnpackItemID(&((*apidl)->mkid),&data);
789 lstrcpynW(arg,data.cFileName,MAX_PATH);
790 LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_ERASEITEM,message,
791 sizeof(message)/sizeof(WCHAR));
792 break;
794 default:
796 static const WCHAR format[]={'%','u','\0'};
797 LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_ERASEMULTIPLE,
798 message,sizeof(message)/sizeof(WCHAR));
799 sprintfW(arg,format,cidl);
800 break;
804 LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_ERASE_CAPTION,caption,
805 sizeof(caption)/sizeof(WCHAR));
806 if(ShellMessageBoxW(shell32_hInstance,parent,message,caption,
807 MB_YESNO|MB_ICONEXCLAMATION,arg)!=IDYES)
808 return ret;
811 SHGetFolderLocation(parent,CSIDL_BITBUCKET,0,0,&recyclebin);
812 for (; i<cidl; i++)
814 if(SUCCEEDED(TRASH_EraseItem(apidl[i])))
815 SHChangeNotify(SHCNE_DELETE,SHCNF_IDLIST,
816 ILCombine(recyclebin,apidl[i]),0);
818 ILFree(recyclebin);
819 return S_OK;
822 static HRESULT WINAPI RecycleBin_DeleteItems(ISFHelper * iface, UINT cidl,
823 LPCITEMIDLIST * apidl)
825 TRACE("(%p,%u,%p)\n",iface,cidl,apidl);
826 return erase_items(GetActiveWindow(),apidl,cidl,TRUE);
829 static HRESULT WINAPI RecycleBin_CopyItems(ISFHelper * iface,
830 IShellFolder * pSFFrom,
831 UINT cidl, LPCITEMIDLIST * apidl)
833 return E_NOTIMPL;
836 static const ISFHelperVtbl sfhelperVtbl =
838 RecycleBin_ISFHelper_QueryInterface,
839 RecycleBin_ISFHelper_AddRef,
840 RecycleBin_ISFHelper_Release,
841 RecycleBin_GetUniqueName,
842 RecycleBin_AddFolder,
843 RecycleBin_DeleteItems,
844 RecycleBin_CopyItems
847 HRESULT WINAPI SHQueryRecycleBinA(LPCSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo)
849 WCHAR wszRootPath[MAX_PATH];
850 MultiByteToWideChar(CP_ACP, 0, pszRootPath, -1, wszRootPath, MAX_PATH);
851 return SHQueryRecycleBinW(wszRootPath, pSHQueryRBInfo);
854 HRESULT WINAPI SHQueryRecycleBinW(LPCWSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo)
856 LPITEMIDLIST *apidl;
857 INT cidl;
858 INT i=0;
859 HRESULT hr;
861 TRACE("(%s, %p)\n", debugstr_w(pszRootPath), pSHQueryRBInfo);
863 hr = TRASH_EnumItems(pszRootPath, &apidl, &cidl);
864 if (FAILED(hr))
865 return hr;
866 pSHQueryRBInfo->i64NumItems = cidl;
867 pSHQueryRBInfo->i64Size = 0;
868 for (; i<cidl; i++)
870 WIN32_FIND_DATAW data;
871 TRASH_UnpackItemID(&((apidl[i])->mkid),&data);
872 pSHQueryRBInfo->i64Size += ((DWORDLONG)data.nFileSizeHigh << 32) + data.nFileSizeLow;
873 ILFree(apidl[i]);
875 SHFree(apidl);
876 return S_OK;
879 HRESULT WINAPI SHEmptyRecycleBinA(HWND hwnd, LPCSTR pszRootPath, DWORD dwFlags)
881 WCHAR wszRootPath[MAX_PATH];
882 MultiByteToWideChar(CP_ACP, 0, pszRootPath, -1, wszRootPath, MAX_PATH);
883 return SHEmptyRecycleBinW(hwnd, wszRootPath, dwFlags);
886 #define SHERB_NOCONFIRMATION 1
887 #define SHERB_NOPROGRESSUI 2
888 #define SHERB_NOSOUND 4
890 HRESULT WINAPI SHEmptyRecycleBinW(HWND hwnd, LPCWSTR pszRootPath, DWORD dwFlags)
892 LPITEMIDLIST *apidl;
893 INT cidl;
894 INT i=0;
895 HRESULT ret;
897 TRACE("(%p, %s, 0x%08x)\n", hwnd, debugstr_w(pszRootPath) , dwFlags);
899 ret = TRASH_EnumItems(pszRootPath, &apidl, &cidl);
900 if (FAILED(ret))
901 return ret;
903 ret = erase_items(hwnd,(const LPCITEMIDLIST*)apidl,cidl,!(dwFlags & SHERB_NOCONFIRMATION));
904 for (;i<cidl;i++)
905 ILFree(apidl[i]);
906 SHFree(apidl);
907 return ret;
910 /*************************************************************************
911 * SHUpdateRecycleBinIcon [SHELL32.@]
913 * Undocumented
915 HRESULT WINAPI SHUpdateRecycleBinIcon(void)
917 FIXME("stub\n");
918 return S_OK;