dmscript: Merge the IClassFactory implementations.
[wine/testsucceed.git] / dlls / shell32 / recyclebin.c
blob39b662abc3d0edb9752149ba492f9dfd622104c2
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 "ntquery.h"
35 #include "shlwapi.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 "enumidlist.h"
45 #include "xdg.h"
46 #include "pidl.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(recyclebin);
50 typedef struct
52 int column_name_id;
53 const GUID *fmtId;
54 DWORD pid;
55 int pcsFlags;
56 int fmt;
57 int cxChars;
58 } columninfo;
60 static const columninfo RecycleBinColumns[] =
62 {IDS_SHV_COLUMN1, &FMTID_Storage, PID_STG_NAME, SHCOLSTATE_TYPE_STR|SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 30},
63 {IDS_SHV_COLUMN_DELFROM, &FMTID_Displaced, PID_DISPLACED_FROM, SHCOLSTATE_TYPE_STR|SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 30},
64 {IDS_SHV_COLUMN_DELDATE, &FMTID_Displaced, PID_DISPLACED_DATE, SHCOLSTATE_TYPE_DATE|SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 20},
65 {IDS_SHV_COLUMN2, &FMTID_Storage, PID_STG_SIZE, SHCOLSTATE_TYPE_INT|SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 20},
66 {IDS_SHV_COLUMN3, &FMTID_Storage, PID_STG_STORAGETYPE,SHCOLSTATE_TYPE_INT|SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 20},
67 {IDS_SHV_COLUMN4, &FMTID_Storage, PID_STG_WRITETIME, SHCOLSTATE_TYPE_DATE|SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 20},
68 /* {"creation time", &FMTID_Storage, PID_STG_CREATETIME, SHCOLSTATE_TYPE_DATE, LVCFMT_LEFT, 20}, */
69 /* {"attribs", &FMTID_Storage, PID_STG_ATTRIBUTES, SHCOLSTATE_TYPE_STR, LVCFMT_LEFT, 20}, */
72 #define COLUMN_NAME 0
73 #define COLUMN_DELFROM 1
74 #define COLUMN_DATEDEL 2
75 #define COLUMN_SIZE 3
76 #define COLUMN_TYPE 4
77 #define COLUMN_MTIME 5
79 #define COLUMNS_COUNT 6
81 static HRESULT FormatDateTime(LPWSTR buffer, int size, FILETIME ft)
83 FILETIME lft;
84 SYSTEMTIME time;
85 int ret;
87 FileTimeToLocalFileTime(&ft, &lft);
88 FileTimeToSystemTime(&lft, &time);
90 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, buffer, size);
91 if (ret>0 && ret<size)
93 /* Append space + time without seconds */
94 buffer[ret-1] = ' ';
95 GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &buffer[ret], size - ret);
98 return (ret!=0 ? E_FAIL : S_OK);
101 typedef struct tagRecycleBinMenu
103 IContextMenu2 IContextMenu2_iface;
104 LONG refCount;
106 UINT cidl;
107 LPITEMIDLIST *apidl;
108 IShellFolder2 *folder;
109 } RecycleBinMenu;
111 static const IContextMenu2Vtbl recycleBinMenuVtbl;
113 static RecycleBinMenu *impl_from_IContextMenu2(IContextMenu2 *iface)
115 return CONTAINING_RECORD(iface, RecycleBinMenu, IContextMenu2_iface);
118 static IContextMenu2* RecycleBinMenu_Constructor(UINT cidl, LPCITEMIDLIST *apidl, IShellFolder2 *folder)
120 RecycleBinMenu *This = SHAlloc(sizeof(RecycleBinMenu));
121 TRACE("(%u,%p)\n",cidl,apidl);
122 This->IContextMenu2_iface.lpVtbl = &recycleBinMenuVtbl;
123 This->cidl = cidl;
124 This->apidl = _ILCopyaPidl(apidl,cidl);
125 IShellFolder2_AddRef(folder);
126 This->folder = folder;
127 This->refCount = 1;
128 return &This->IContextMenu2_iface;
131 static HRESULT WINAPI RecycleBinMenu_QueryInterface(IContextMenu2 *iface,
132 REFIID riid,
133 void **ppvObject)
135 RecycleBinMenu *This = impl_from_IContextMenu2(iface);
136 TRACE("(%p, %s, %p) - stub\n", This, debugstr_guid(riid), ppvObject);
137 return E_NOTIMPL;
140 static ULONG WINAPI RecycleBinMenu_AddRef(IContextMenu2 *iface)
142 RecycleBinMenu *This = impl_from_IContextMenu2(iface);
143 TRACE("(%p)\n", This);
144 return InterlockedIncrement(&This->refCount);
148 static ULONG WINAPI RecycleBinMenu_Release(IContextMenu2 *iface)
150 RecycleBinMenu *This = impl_from_IContextMenu2(iface);
151 UINT result;
152 TRACE("(%p)\n", This);
153 result = InterlockedDecrement(&This->refCount);
154 if (result == 0)
156 TRACE("Destroying object\n");
157 _ILFreeaPidl(This->apidl,This->cidl);
158 IShellFolder_Release(This->folder);
159 SHFree(This);
161 return result;
164 static HRESULT WINAPI RecycleBinMenu_QueryContextMenu(IContextMenu2 *iface,
165 HMENU hmenu,
166 UINT indexMenu,
167 UINT idCmdFirst,
168 UINT idCmdLast,
169 UINT uFlags)
171 HMENU menures = LoadMenuW(shell32_hInstance,MAKEINTRESOURCEW(MENU_RECYCLEBIN));
172 if(uFlags & CMF_DEFAULTONLY)
173 return E_NOTIMPL;
174 else{
175 UINT idMax = Shell_MergeMenus(hmenu,GetSubMenu(menures,0),indexMenu,idCmdFirst,idCmdLast,MM_SUBMENUSHAVEIDS);
176 TRACE("Added %d id(s)\n",idMax-idCmdFirst);
177 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst+1);
181 static void DoErase(RecycleBinMenu *This)
183 ISFHelper *helper;
184 IShellFolder2_QueryInterface(This->folder,&IID_ISFHelper,(void**)&helper);
185 if(helper)
186 ISFHelper_DeleteItems(helper,This->cidl,(LPCITEMIDLIST*)This->apidl);
189 static void DoRestore(RecycleBinMenu *This)
192 /*TODO add prompts*/
193 UINT i;
194 for(i=0;i<This->cidl;i++)
196 WIN32_FIND_DATAW data;
197 TRASH_UnpackItemID(&((This->apidl[i])->mkid),&data);
198 if(PathFileExistsW(data.cFileName))
200 PIDLIST_ABSOLUTE dest_pidl = ILCreateFromPathW(data.cFileName);
201 WCHAR message[100];
202 WCHAR caption[50];
203 if(_ILIsFolder(ILFindLastID(dest_pidl)))
204 LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_OVERWRITEFOLDER,
205 message,sizeof(message)/sizeof(WCHAR));
206 else
207 LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_OVERWRITEFILE,
208 message,sizeof(message)/sizeof(WCHAR));
209 LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_OVERWRITE_CAPTION,
210 caption,sizeof(caption)/sizeof(WCHAR));
212 if(ShellMessageBoxW(shell32_hInstance,GetActiveWindow(),message,
213 caption,MB_YESNO|MB_ICONEXCLAMATION,
214 data.cFileName)!=IDYES)
215 continue;
217 if(SUCCEEDED(TRASH_RestoreItem(This->apidl[i])))
219 IPersistFolder2 *persist;
220 LPITEMIDLIST root_pidl;
221 PIDLIST_ABSOLUTE dest_pidl = ILCreateFromPathW(data.cFileName);
222 BOOL is_folder = _ILIsFolder(ILFindLastID(dest_pidl));
223 IShellFolder2_QueryInterface(This->folder,&IID_IPersistFolder2,
224 (void**)&persist);
225 IPersistFolder2_GetCurFolder(persist,&root_pidl);
226 SHChangeNotify(is_folder ? SHCNE_RMDIR : SHCNE_DELETE,
227 SHCNF_IDLIST,ILCombine(root_pidl,This->apidl[i]),0);
228 SHChangeNotify(is_folder ? SHCNE_MKDIR : SHCNE_CREATE,
229 SHCNF_IDLIST,dest_pidl,0);
230 ILFree(dest_pidl);
231 ILFree(root_pidl);
236 static HRESULT WINAPI RecycleBinMenu_InvokeCommand(IContextMenu2 *iface,
237 LPCMINVOKECOMMANDINFO pici)
239 RecycleBinMenu *This = impl_from_IContextMenu2(iface);
240 LPCSTR verb = pici->lpVerb;
241 if(!HIWORD(verb))
243 switch((UINT)verb)
245 case IDM_RECYCLEBIN_ERASE:
246 DoErase(This);
247 break;
248 case IDM_RECYCLEBIN_RESTORE:
249 DoRestore(This);
250 break;
251 default:
252 return E_NOTIMPL;
255 return S_OK;
258 static HRESULT WINAPI RecycleBinMenu_GetCommandString(IContextMenu2 *iface,
259 UINT_PTR idCmd,
260 UINT uType,
261 UINT *pwReserved,
262 LPSTR pszName,
263 UINT cchMax)
265 TRACE("(%p, %lu, %u, %p, %s, %u) - stub\n",iface,idCmd,uType,pwReserved,debugstr_a(pszName),cchMax);
266 return E_NOTIMPL;
269 static HRESULT WINAPI RecycleBinMenu_HandleMenuMsg(IContextMenu2 *iface,
270 UINT uMsg, WPARAM wParam,
271 LPARAM lParam)
273 TRACE("(%p, %u, 0x%lx, 0x%lx) - stub\n",iface,uMsg,wParam,lParam);
274 return E_NOTIMPL;
278 static const IContextMenu2Vtbl recycleBinMenuVtbl =
280 RecycleBinMenu_QueryInterface,
281 RecycleBinMenu_AddRef,
282 RecycleBinMenu_Release,
283 RecycleBinMenu_QueryContextMenu,
284 RecycleBinMenu_InvokeCommand,
285 RecycleBinMenu_GetCommandString,
286 RecycleBinMenu_HandleMenuMsg,
290 * Recycle Bin folder
293 typedef struct tagRecycleBin
295 IShellFolder2 IShellFolder2_iface;
296 IPersistFolder2 IPersistFolder2_iface;
297 ISFHelper ISFHelper_iface;
298 LONG refCount;
300 LPITEMIDLIST pidl;
301 } RecycleBin;
303 static const IShellFolder2Vtbl recycleBinVtbl;
304 static const IPersistFolder2Vtbl recycleBinPersistVtbl;
305 static const ISFHelperVtbl sfhelperVtbl;
307 static inline RecycleBin *impl_from_IShellFolder2(IShellFolder2 *iface)
309 return CONTAINING_RECORD(iface, RecycleBin, IShellFolder2_iface);
312 static RecycleBin *impl_from_IPersistFolder2(IPersistFolder2 *iface)
314 return CONTAINING_RECORD(iface, RecycleBin, IPersistFolder2_iface);
317 static RecycleBin *impl_from_ISFHelper(ISFHelper *iface)
319 return CONTAINING_RECORD(iface, RecycleBin, ISFHelper_iface);
322 static void RecycleBin_Destructor(RecycleBin *This);
324 HRESULT WINAPI RecycleBin_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppOutput)
326 RecycleBin *obj;
327 HRESULT ret;
328 if (pUnkOuter)
329 return CLASS_E_NOAGGREGATION;
331 obj = SHAlloc(sizeof(RecycleBin));
332 if (obj == NULL)
333 return E_OUTOFMEMORY;
334 ZeroMemory(obj, sizeof(RecycleBin));
335 obj->IShellFolder2_iface.lpVtbl = &recycleBinVtbl;
336 obj->IPersistFolder2_iface.lpVtbl = &recycleBinPersistVtbl;
337 obj->ISFHelper_iface.lpVtbl = &sfhelperVtbl;
338 if (FAILED(ret = IPersistFolder2_QueryInterface(&obj->IPersistFolder2_iface, riid, ppOutput)))
340 RecycleBin_Destructor(obj);
341 return ret;
343 /* InterlockedIncrement(&objCount);*/
344 return S_OK;
347 static void RecycleBin_Destructor(RecycleBin *This)
349 /* InterlockedDecrement(&objCount);*/
350 SHFree(This->pidl);
351 SHFree(This);
354 static HRESULT WINAPI RecycleBin_QueryInterface(IShellFolder2 *iface, REFIID riid, void **ppvObject)
356 RecycleBin *This = impl_from_IShellFolder2(iface);
357 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObject);
359 *ppvObject = NULL;
360 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IShellFolder)
361 || IsEqualGUID(riid, &IID_IShellFolder2))
362 *ppvObject = This;
364 if (IsEqualGUID(riid, &IID_IPersist) || IsEqualGUID(riid, &IID_IPersistFolder)
365 || IsEqualGUID(riid, &IID_IPersistFolder2))
366 *ppvObject = &This->IPersistFolder2_iface;
367 if (IsEqualGUID(riid, &IID_ISFHelper))
368 *ppvObject = &This->ISFHelper_iface;
370 if (*ppvObject != NULL)
372 IUnknown_AddRef((IUnknown *)*ppvObject);
373 return S_OK;
375 WARN("no interface %s\n", debugstr_guid(riid));
376 return E_NOINTERFACE;
379 static ULONG WINAPI RecycleBin_AddRef(IShellFolder2 *iface)
381 RecycleBin *This = impl_from_IShellFolder2(iface);
382 TRACE("(%p)\n", This);
383 return InterlockedIncrement(&This->refCount);
386 static ULONG WINAPI RecycleBin_Release(IShellFolder2 *iface)
388 RecycleBin *This = impl_from_IShellFolder2(iface);
389 LONG result;
391 TRACE("(%p)\n", This);
392 result = InterlockedDecrement(&This->refCount);
393 if (result == 0)
395 TRACE("Destroy object\n");
396 RecycleBin_Destructor(This);
398 return result;
401 static HRESULT WINAPI RecycleBin_ParseDisplayName(IShellFolder2 *This, HWND hwnd, LPBC pbc,
402 LPOLESTR pszDisplayName, ULONG *pchEaten, LPITEMIDLIST *ppidl,
403 ULONG *pdwAttributes)
405 FIXME("stub\n");
406 return E_NOTIMPL;
409 static HRESULT WINAPI RecycleBin_EnumObjects(IShellFolder2 *iface, HWND hwnd, SHCONTF grfFlags, IEnumIDList **ppenumIDList)
411 RecycleBin *This = impl_from_IShellFolder2(iface);
412 IEnumIDList *list;
413 LPITEMIDLIST *pidls;
414 HRESULT ret;
415 int pidls_count;
416 int i=0;
418 TRACE("(%p, %p, %x, %p)\n", This, hwnd, grfFlags, ppenumIDList);
420 if (grfFlags & SHCONTF_NONFOLDERS)
422 *ppenumIDList = NULL;
423 if (FAILED(ret = TRASH_EnumItems(&pidls, &pidls_count)))
424 return ret;
426 list = IEnumIDList_Constructor();
427 if (list == NULL)
428 goto failed;
429 for (i=0; i<pidls_count; i++)
430 if (!AddToEnumList(list, pidls[i]))
431 goto failed;
432 *ppenumIDList = list;
434 else
436 *ppenumIDList = IEnumIDList_Constructor();
437 if (*ppenumIDList == NULL)
438 return E_OUTOFMEMORY;
441 return S_OK;
443 failed:
444 if (list)
445 IEnumIDList_Release(list);
446 for (; i<pidls_count; i++)
447 ILFree(pidls[i]);
448 SHFree(pidls);
449 return E_OUTOFMEMORY;
452 static HRESULT WINAPI RecycleBin_BindToObject(IShellFolder2 *This, LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppv)
454 FIXME("(%p, %p, %p, %s, %p) - stub\n", This, pidl, pbc, debugstr_guid(riid), ppv);
455 return E_NOTIMPL;
458 static HRESULT WINAPI RecycleBin_BindToStorage(IShellFolder2 *This, LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppv)
460 FIXME("(%p, %p, %p, %s, %p) - stub\n", This, pidl, pbc, debugstr_guid(riid), ppv);
461 return E_NOTIMPL;
464 static HRESULT WINAPI RecycleBin_CompareIDs(IShellFolder2 *iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
466 RecycleBin *This = impl_from_IShellFolder2(iface);
468 /* TODO */
469 TRACE("(%p, %p, %p, %p)\n", This, (void *)lParam, pidl1, pidl2);
470 if (pidl1->mkid.cb != pidl2->mkid.cb)
471 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, pidl1->mkid.cb - pidl2->mkid.cb);
472 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (unsigned short)memcmp(pidl1->mkid.abID, pidl2->mkid.abID, pidl1->mkid.cb));
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;
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 pName->u.pOleStr = StrDupW(PathFindFileNameW(data.cFileName));
533 if (pName->u.pOleStr == NULL)
534 return E_OUTOFMEMORY;
536 return S_OK;
539 static HRESULT WINAPI RecycleBin_SetNameOf(IShellFolder2 *This, HWND hwnd, LPCITEMIDLIST pidl, LPCOLESTR pszName,
540 SHGDNF uFlags, LPITEMIDLIST *ppidlOut)
542 TRACE("\n");
543 return E_FAIL; /* not supported */
546 static HRESULT WINAPI RecycleBin_GetClassID(IPersistFolder2 *This, CLSID *pClassID)
548 TRACE("(%p, %p)\n", This, pClassID);
549 if (This == NULL || pClassID == NULL)
550 return E_INVALIDARG;
551 *pClassID = CLSID_RecycleBin;
552 return S_OK;
555 static HRESULT WINAPI RecycleBin_Initialize(IPersistFolder2 *iface, LPCITEMIDLIST pidl)
557 RecycleBin *This = impl_from_IPersistFolder2(iface);
558 TRACE("(%p, %p)\n", This, pidl);
560 This->pidl = ILClone(pidl);
561 if (This->pidl == NULL)
562 return E_OUTOFMEMORY;
563 return S_OK;
566 static HRESULT WINAPI RecycleBin_GetCurFolder(IPersistFolder2 *iface, LPITEMIDLIST *ppidl)
568 RecycleBin *This = impl_from_IPersistFolder2(iface);
569 TRACE("\n");
570 *ppidl = ILClone(This->pidl);
571 return S_OK;
574 static HRESULT WINAPI RecycleBin_GetDefaultSearchGUID(IShellFolder2 *iface, GUID *pguid)
576 FIXME("stub\n");
577 return E_NOTIMPL;
580 static HRESULT WINAPI RecycleBin_EnumSearches(IShellFolder2 *iface, IEnumExtraSearch **ppEnum)
582 FIXME("stub\n");
583 *ppEnum = NULL;
584 return E_NOTIMPL;
587 static HRESULT WINAPI RecycleBin_GetDefaultColumn(IShellFolder2 *iface, DWORD dwReserved, ULONG *pSort, ULONG *pDisplay)
589 RecycleBin *This = impl_from_IShellFolder2(iface);
590 TRACE("(%p, %x, %p, %p)\n", This, dwReserved, pSort, pDisplay);
591 *pSort = 0;
592 *pDisplay = 0;
593 return S_OK;
596 static HRESULT WINAPI RecycleBin_GetDefaultColumnState(IShellFolder2 *iface, UINT iColumn, SHCOLSTATEF *pcsFlags)
598 RecycleBin *This = impl_from_IShellFolder2(iface);
599 TRACE("(%p, %d, %p)\n", This, iColumn, pcsFlags);
600 if (iColumn >= COLUMNS_COUNT)
601 return E_INVALIDARG;
602 *pcsFlags = RecycleBinColumns[iColumn].pcsFlags;
603 return S_OK;
606 static HRESULT WINAPI RecycleBin_GetDetailsEx(IShellFolder2 *iface, LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
608 FIXME("stub\n");
609 return E_NOTIMPL;
612 static HRESULT WINAPI RecycleBin_GetDetailsOf(IShellFolder2 *iface, LPCITEMIDLIST pidl, UINT iColumn, LPSHELLDETAILS pDetails)
614 RecycleBin *This = impl_from_IShellFolder2(iface);
615 WIN32_FIND_DATAW data;
616 WCHAR buffer[MAX_PATH];
618 TRACE("(%p, %p, %d, %p)\n", This, pidl, iColumn, pDetails);
619 if (iColumn >= COLUMNS_COUNT)
620 return E_FAIL;
621 pDetails->fmt = RecycleBinColumns[iColumn].fmt;
622 pDetails->cxChar = RecycleBinColumns[iColumn].cxChars;
623 if (pidl == NULL)
625 pDetails->str.uType = STRRET_WSTR;
626 LoadStringW(shell32_hInstance, RecycleBinColumns[iColumn].column_name_id, buffer, MAX_PATH);
627 return SHStrDupW(buffer, &pDetails->str.u.pOleStr);
630 if (iColumn == COLUMN_NAME)
631 return RecycleBin_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL, &pDetails->str);
633 TRASH_UnpackItemID(&pidl->mkid, &data);
634 switch (iColumn)
636 case COLUMN_DATEDEL:
637 FormatDateTime(buffer, MAX_PATH, data.ftLastAccessTime);
638 break;
639 case COLUMN_DELFROM:
640 lstrcpyW(buffer, data.cFileName);
641 PathRemoveFileSpecW(buffer);
642 break;
643 case COLUMN_SIZE:
644 StrFormatKBSizeW(((LONGLONG)data.nFileSizeHigh<<32)|data.nFileSizeLow, buffer, MAX_PATH);
645 break;
646 case COLUMN_MTIME:
647 FormatDateTime(buffer, MAX_PATH, data.ftLastWriteTime);
648 break;
649 case COLUMN_TYPE:
650 /* TODO */
651 buffer[0] = 0;
652 break;
653 default:
654 return E_FAIL;
657 pDetails->str.uType = STRRET_WSTR;
658 return SHStrDupW(buffer, &pDetails->str.u.pOleStr);
661 static HRESULT WINAPI RecycleBin_MapColumnToSCID(IShellFolder2 *iface, UINT iColumn, SHCOLUMNID *pscid)
663 RecycleBin *This = impl_from_IShellFolder2(iface);
664 TRACE("(%p, %d, %p)\n", This, iColumn, pscid);
665 if (iColumn>=COLUMNS_COUNT)
666 return E_INVALIDARG;
667 pscid->fmtid = *RecycleBinColumns[iColumn].fmtId;
668 pscid->pid = RecycleBinColumns[iColumn].pid;
669 return S_OK;
672 static const IShellFolder2Vtbl recycleBinVtbl =
674 /* IUnknown */
675 RecycleBin_QueryInterface,
676 RecycleBin_AddRef,
677 RecycleBin_Release,
679 /* IShellFolder */
680 RecycleBin_ParseDisplayName,
681 RecycleBin_EnumObjects,
682 RecycleBin_BindToObject,
683 RecycleBin_BindToStorage,
684 RecycleBin_CompareIDs,
685 RecycleBin_CreateViewObject,
686 RecycleBin_GetAttributesOf,
687 RecycleBin_GetUIObjectOf,
688 RecycleBin_GetDisplayNameOf,
689 RecycleBin_SetNameOf,
691 /* IShellFolder2 */
692 RecycleBin_GetDefaultSearchGUID,
693 RecycleBin_EnumSearches,
694 RecycleBin_GetDefaultColumn,
695 RecycleBin_GetDefaultColumnState,
696 RecycleBin_GetDetailsEx,
697 RecycleBin_GetDetailsOf,
698 RecycleBin_MapColumnToSCID
701 static HRESULT WINAPI RecycleBin_IPersistFolder2_QueryInterface(IPersistFolder2 *iface, REFIID riid,
702 void **ppvObject)
704 RecycleBin *This = impl_from_IPersistFolder2(iface);
706 return RecycleBin_QueryInterface(&This->IShellFolder2_iface, riid, ppvObject);
709 static ULONG WINAPI RecycleBin_IPersistFolder2_AddRef(IPersistFolder2 *iface)
711 RecycleBin *This = impl_from_IPersistFolder2(iface);
713 return RecycleBin_AddRef(&This->IShellFolder2_iface);
716 static ULONG WINAPI RecycleBin_IPersistFolder2_Release(IPersistFolder2 *iface)
718 RecycleBin *This = impl_from_IPersistFolder2(iface);
720 return RecycleBin_Release(&This->IShellFolder2_iface);
723 static const IPersistFolder2Vtbl recycleBinPersistVtbl =
725 /* IUnknown */
726 RecycleBin_IPersistFolder2_QueryInterface,
727 RecycleBin_IPersistFolder2_AddRef,
728 RecycleBin_IPersistFolder2_Release,
730 /* IPersist */
731 RecycleBin_GetClassID,
732 /* IPersistFolder */
733 RecycleBin_Initialize,
734 /* IPersistFolder2 */
735 RecycleBin_GetCurFolder
738 static HRESULT WINAPI RecycleBin_ISFHelper_QueryInterface(ISFHelper *iface, REFIID riid,
739 void **ppvObject)
741 RecycleBin *This = impl_from_ISFHelper(iface);
743 return RecycleBin_QueryInterface(&This->IShellFolder2_iface, riid, ppvObject);
746 static ULONG WINAPI RecycleBin_ISFHelper_AddRef(ISFHelper *iface)
748 RecycleBin *This = impl_from_ISFHelper(iface);
750 return RecycleBin_AddRef(&This->IShellFolder2_iface);
753 static ULONG WINAPI RecycleBin_ISFHelper_Release(ISFHelper *iface)
755 RecycleBin *This = impl_from_ISFHelper(iface);
757 return RecycleBin_Release(&This->IShellFolder2_iface);
760 static HRESULT WINAPI RecycleBin_GetUniqueName(ISFHelper *iface,LPWSTR lpName,
761 UINT uLen)
763 return E_NOTIMPL;
766 static HRESULT WINAPI RecycleBin_AddFolder(ISFHelper * iface, HWND hwnd,
767 LPCWSTR pwszName,
768 LPITEMIDLIST * ppidlOut)
770 /*Adding folders doesn't make sense in the recycle bin*/
771 return E_NOTIMPL;
774 static HRESULT erase_items(HWND parent,const LPCITEMIDLIST * apidl, UINT cidl, BOOL confirm)
776 UINT i=0;
777 HRESULT ret = S_OK;
778 LPITEMIDLIST recyclebin;
780 if(confirm)
782 WCHAR arg[MAX_PATH];
783 WCHAR message[100];
784 WCHAR caption[50];
785 switch(cidl)
787 case 0:
788 return S_OK;
789 case 1:
791 WIN32_FIND_DATAW data;
792 TRASH_UnpackItemID(&((*apidl)->mkid),&data);
793 lstrcpynW(arg,data.cFileName,MAX_PATH);
794 LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_ERASEITEM,message,
795 sizeof(message)/sizeof(WCHAR));
796 break;
798 default:
800 static const WCHAR format[]={'%','u','\0'};
801 LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_ERASEMULTIPLE,
802 message,sizeof(message)/sizeof(WCHAR));
803 sprintfW(arg,format,cidl);
804 break;
808 LoadStringW(shell32_hInstance,IDS_RECYCLEBIN_ERASE_CAPTION,caption,
809 sizeof(caption)/sizeof(WCHAR));
810 if(ShellMessageBoxW(shell32_hInstance,parent,message,caption,
811 MB_YESNO|MB_ICONEXCLAMATION,arg)!=IDYES)
812 return ret;
815 SHGetFolderLocation(parent,CSIDL_BITBUCKET,0,0,&recyclebin);
816 for (; i<cidl; i++)
818 if(SUCCEEDED(TRASH_EraseItem(apidl[i])))
819 SHChangeNotify(SHCNE_DELETE,SHCNF_IDLIST,
820 ILCombine(recyclebin,apidl[i]),0);
822 ILFree(recyclebin);
823 return S_OK;
826 static HRESULT WINAPI RecycleBin_DeleteItems(ISFHelper * iface, UINT cidl,
827 LPCITEMIDLIST * apidl)
829 TRACE("(%p,%u,%p)\n",iface,cidl,apidl);
830 return erase_items(GetActiveWindow(),apidl,cidl,TRUE);
833 static HRESULT WINAPI RecycleBin_CopyItems(ISFHelper * iface,
834 IShellFolder * pSFFrom,
835 UINT cidl, LPCITEMIDLIST * apidl)
837 return E_NOTIMPL;
840 static const ISFHelperVtbl sfhelperVtbl =
842 RecycleBin_ISFHelper_QueryInterface,
843 RecycleBin_ISFHelper_AddRef,
844 RecycleBin_ISFHelper_Release,
845 RecycleBin_GetUniqueName,
846 RecycleBin_AddFolder,
847 RecycleBin_DeleteItems,
848 RecycleBin_CopyItems
851 HRESULT WINAPI SHQueryRecycleBinA(LPCSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo)
853 WCHAR wszRootPath[MAX_PATH];
854 MultiByteToWideChar(CP_ACP, 0, pszRootPath, -1, wszRootPath, MAX_PATH);
855 return SHQueryRecycleBinW(wszRootPath, pSHQueryRBInfo);
858 HRESULT WINAPI SHQueryRecycleBinW(LPCWSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo)
860 LPITEMIDLIST *apidl;
861 INT cidl;
862 INT i=0;
863 TRACE("(%s, %p)\n", debugstr_w(pszRootPath), pSHQueryRBInfo);
864 FIXME("Ignoring pszRootPath=%s\n",debugstr_w(pszRootPath));
866 TRASH_EnumItems(&apidl,&cidl);
867 pSHQueryRBInfo->i64NumItems = cidl;
868 pSHQueryRBInfo->i64Size = 0;
869 for (; i<cidl; i++)
871 WIN32_FIND_DATAW data;
872 TRASH_UnpackItemID(&((apidl[i])->mkid),&data);
873 pSHQueryRBInfo->i64Size += ((DWORDLONG)data.nFileSizeHigh << 32) + data.nFileSizeLow;
874 ILFree(apidl[i]);
876 SHFree(apidl);
877 return S_OK;
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)
893 LPITEMIDLIST *apidl;
894 INT cidl;
895 INT i=0;
896 HRESULT ret;
897 TRACE("(%p, %s, 0x%08x)\n", hwnd, debugstr_w(pszRootPath) , dwFlags);
898 FIXME("Ignoring pszRootPath=%s\n",debugstr_w(pszRootPath));
899 TRASH_EnumItems(&apidl,&cidl);
900 ret = erase_items(hwnd,(const LPCITEMIDLIST*)apidl,cidl,!(dwFlags & SHERB_NOCONFIRMATION));
901 for (;i<cidl;i++)
902 ILFree(apidl[i]);
903 SHFree(apidl);
904 return ret;
907 /*************************************************************************
908 * SHUpdateRecycleBinIcon [SHELL32.@]
910 * Undocumented
912 HRESULT WINAPI SHUpdateRecycleBinIcon(void)
914 FIXME("stub\n");
915 return S_OK;