2 * Trash virtual folder support. The trashing engine is implemented in trash.c
4 * Copyright (C) 2006 Mikolaj Zalewski
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define MAX_PROPERTY_SHEET_PAGE 32
25 WINE_DEFAULT_DEBUG_CHANNEL(recyclebin
);
37 static const columninfo RecycleBinColumns
[] =
39 {IDS_SHV_COLUMN1
, &FMTID_Storage
, PID_STG_NAME
, SHCOLSTATE_TYPE_STR
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 30},
40 {IDS_SHV_COLUMN_DELFROM
, &FMTID_Displaced
, PID_DISPLACED_FROM
, SHCOLSTATE_TYPE_STR
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 30},
41 {IDS_SHV_COLUMN_DELDATE
, &FMTID_Displaced
, PID_DISPLACED_DATE
, SHCOLSTATE_TYPE_DATE
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 20},
42 {IDS_SHV_COLUMN2
, &FMTID_Storage
, PID_STG_SIZE
, SHCOLSTATE_TYPE_INT
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 20},
43 {IDS_SHV_COLUMN3
, &FMTID_Storage
, PID_STG_STORAGETYPE
,SHCOLSTATE_TYPE_INT
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 20},
44 {IDS_SHV_COLUMN4
, &FMTID_Storage
, PID_STG_WRITETIME
, SHCOLSTATE_TYPE_DATE
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 20},
45 /* {"creation time", &FMTID_Storage, PID_STG_CREATETIME, SHCOLSTATE_TYPE_DATE, LVCFMT_LEFT, 20}, */
46 /* {"attribs", &FMTID_Storage, PID_STG_ATTRIBUTES, SHCOLSTATE_TYPE_STR, LVCFMT_LEFT, 20}, */
50 #define COLUMN_DELFROM 1
51 #define COLUMN_DATEDEL 2
54 #define COLUMN_MTIME 5
56 #define COLUMNS_COUNT 6
62 typedef struct tagRecycleBin
64 const IShellFolder2Vtbl
*lpVtbl
;
65 const IPersistFolder2Vtbl
*lpPersistFolderVtbl
;
66 const IContextMenu2Vtbl
*lpContextMenu2
;
67 const IShellExtInitVtbl
*lpSEI
;
72 } RecycleBin
, *LPRecycleBin
;
76 PIDLRecycleStruct
*pFileDetails
;
79 }SEARCH_CONTEXT
, *PSEARCH_CONTEXT
;
86 }DRIVE_ITEM_CONTEXT
, *PDRIVE_ITEM_CONTEXT
;
89 static const IContextMenu2Vtbl recycleBincmVtblFolder
;
90 static const IContextMenu2Vtbl recycleBincmVtblBitbucketItem
;
91 static const IShellFolder2Vtbl recycleBinVtbl
;
92 static const IPersistFolder2Vtbl recycleBinPersistVtbl
;
93 static const IShellExtInitVtbl eivt
;
95 static LPRecycleBin __inline
impl_from_IContextMenu2(IContextMenu2
*iface
)
97 return (RecycleBin
*)((char *)iface
- FIELD_OFFSET(RecycleBin
, lpContextMenu2
));
100 static LPRecycleBin __inline
impl_from_IPersistFolder(IPersistFolder2
*iface
)
102 return (RecycleBin
*)((char *)iface
- FIELD_OFFSET(RecycleBin
, lpPersistFolderVtbl
));
105 static LPRecycleBin __inline
impl_from_IShellExtInit( IShellExtInit
*iface
)
107 return (RecycleBin
*)((char*)iface
- FIELD_OFFSET(RecycleBin
, lpSEI
));
110 static void RecycleBin_Destructor(RecycleBin
*This
);
112 HRESULT WINAPI
RecycleBin_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, LPVOID
*ppOutput
)
117 return CLASS_E_NOAGGREGATION
;
119 obj
= SHAlloc(sizeof(RecycleBin
));
121 return E_OUTOFMEMORY
;
122 ZeroMemory(obj
, sizeof(RecycleBin
));
123 obj
->lpVtbl
= &recycleBinVtbl
;
125 obj
->lpPersistFolderVtbl
= &recycleBinPersistVtbl
;
126 obj
->lpContextMenu2
= NULL
;
127 if (FAILED(ret
= IUnknown_QueryInterface((IUnknown
*)obj
, riid
, ppOutput
)))
129 RecycleBin_Destructor(obj
);
132 /* InterlockedIncrement(&objCount);*/
136 static void RecycleBin_Destructor(RecycleBin
*This
)
138 /* InterlockedDecrement(&objCount);*/
143 static HRESULT WINAPI
RecycleBin_QueryInterface(IShellFolder2
*iface
, REFIID riid
, void **ppvObject
)
145 RecycleBin
*This
= (RecycleBin
*)iface
;
146 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
149 if (IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_IShellFolder
)
150 || IsEqualGUID(riid
, &IID_IShellFolder2
))
153 if (IsEqualGUID(riid
, &IID_IPersist
) || IsEqualGUID(riid
, &IID_IPersistFolder
)
154 || IsEqualGUID(riid
, &IID_IPersistFolder2
))
155 *ppvObject
= (void *)&This
->lpPersistFolderVtbl
;
157 else if (IsEqualIID(riid
, &IID_IContextMenu
) || IsEqualGUID(riid
, &IID_IContextMenu2
))
159 This
->lpContextMenu2
= &recycleBincmVtblFolder
;
160 *ppvObject
= (void *)&This
->lpContextMenu2
;
162 else if(IsEqualIID(riid
, &IID_IShellExtInit
))
164 *ppvObject
= (void *)&(This
->lpSEI
);
167 if (*ppvObject
!= NULL
)
169 IUnknown_AddRef((IUnknown
*)*ppvObject
);
172 WARN("no interface %s\n", debugstr_guid(riid
));
173 return E_NOINTERFACE
;
176 static ULONG WINAPI
RecycleBin_AddRef(IShellFolder2
*iface
)
178 RecycleBin
*This
= (RecycleBin
*)iface
;
179 TRACE("(%p)\n", This
);
180 return InterlockedIncrement(&This
->refCount
);
183 static ULONG WINAPI
RecycleBin_Release(IShellFolder2
*iface
)
185 RecycleBin
*This
= (RecycleBin
*)iface
;
188 TRACE("(%p)\n", This
);
189 result
= InterlockedDecrement(&This
->refCount
);
192 TRACE("Destroy object\n");
193 RecycleBin_Destructor(This
);
198 static HRESULT WINAPI
RecycleBin_ParseDisplayName(IShellFolder2
*This
, HWND hwnd
, LPBC pbc
,
199 LPOLESTR pszDisplayName
, ULONG
*pchEaten
, LPITEMIDLIST
*ppidl
,
200 ULONG
*pdwAttributes
)
207 PDELETED_FILE_DETAILS_W
208 UnpackDetailsFromPidl(LPCITEMIDLIST pidl
)
210 return (PDELETED_FILE_DETAILS_W
)&pidl
->mkid
.abID
;
213 static LPITEMIDLIST
_ILCreateRecycleItem(PDELETED_FILE_DETAILS_W pFileDetails
)
217 PIDLRecycleStruct
* p
;
218 int size0
= (char*)&tmp
.u
.crecycle
.szName
-(char*)&tmp
.u
.crecycle
;
222 size
+= (wcslen(pFileDetails
->FileName
) + 1) * sizeof(WCHAR
);
224 pidl
= (LPITEMIDLIST
)SHAlloc(size
+ 4);
228 pidl
->mkid
.cb
= size
+2;
229 memcpy(pidl
->mkid
.abID
, &tmp
, 2+size0
);
231 p
= &((PIDLDATA
*)pidl
->mkid
.abID
)->u
.crecycle
;
232 RtlCopyMemory(p
, pFileDetails
, sizeof(DELETED_FILE_DETAILS_W
));
233 wcscpy(p
->szName
, pFileDetails
->FileName
);
234 *(WORD
*)((char*)pidl
+(size
+2)) = 0;
238 static PIDLRecycleStruct
* _ILGetRecycleStruct(LPCITEMIDLIST pidl
)
240 LPPIDLDATA pdata
= _ILGetDataPointer(pidl
);
242 if (pdata
&& pdata
->type
==0x00)
243 return (PIDLRecycleStruct
*)&(pdata
->u
.crecycle
);
250 CBSearchBitBucket(IN PVOID Context
, IN HANDLE hDeletedFile
)
252 PSEARCH_CONTEXT pContext
= (PSEARCH_CONTEXT
)Context
;
254 PDELETED_FILE_DETAILS_W pFileDetails
;
258 if (!GetDeletedFileDetailsW(hDeletedFile
,
262 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
264 ERR("GetDeletedFileDetailsW failed\n");
268 pFileDetails
= SHAlloc(dwSize
);
275 if (!GetDeletedFileDetailsW(hDeletedFile
,
280 ERR("GetDeletedFileDetailsW failed\n");
281 SHFree(pFileDetails
);
285 ret
= memcmp(pFileDetails
, pContext
->pFileDetails
, dwSize
);
288 pContext
->hDeletedFile
= hDeletedFile
;
289 pContext
->bFound
= TRUE
;
292 CloseRecycleBinHandle(hDeletedFile
);
294 SHFree(pFileDetails
);
302 CBEnumBitBucket(IN PVOID Context
, IN HANDLE hDeletedFile
)
304 PDELETED_FILE_DETAILS_W pFileDetails
;
306 LPITEMIDLIST pidl
= NULL
;
309 if (!GetDeletedFileDetailsW(hDeletedFile
,
313 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
315 ERR("GetDeletedFileDetailsW failed\n");
319 pFileDetails
= SHAlloc(dwSize
);
326 if (!GetDeletedFileDetailsW(hDeletedFile
,
331 ERR("GetDeletedFileDetailsW failed\n");
332 SHFree(pFileDetails
);
336 pidl
= _ILCreateRecycleItem(pFileDetails
);
339 SHFree(pFileDetails
);
343 ret
= AddToEnumList((IEnumIDList
*)Context
, pidl
);
347 SHFree(pFileDetails
);
348 TRACE("Returning %d\n", ret
);
349 CloseRecycleBinHandle(hDeletedFile
);
353 static HRESULT WINAPI
RecycleBin_EnumObjects(IShellFolder2
*iface
, HWND hwnd
, SHCONTF grfFlags
, IEnumIDList
**ppenumIDList
)
355 RecycleBin
*This
= (RecycleBin
*)iface
;
357 static LPCWSTR szDrive
= L
"C:\\";
359 TRACE("(%p, %p, %x, %p)\n", This
, hwnd
, (unsigned int)grfFlags
, ppenumIDList
);
361 if (grfFlags
& SHCONTF_NONFOLDERS
)
363 TRACE("Starting Enumeration\n");
364 *ppenumIDList
= NULL
;
365 list
= IEnumIDList_Constructor();
367 return E_OUTOFMEMORY
;
369 if (!EnumerateRecycleBinW(szDrive
, //FIXME
373 WARN("Error: EnumerateRecycleBinW failed\n");
375 *ppenumIDList
= list
;
379 *ppenumIDList
= IEnumIDList_Constructor();
380 if (*ppenumIDList
== NULL
)
381 return E_OUTOFMEMORY
;
388 static HRESULT WINAPI
RecycleBin_BindToObject(IShellFolder2
*This
, LPCITEMIDLIST pidl
, LPBC pbc
, REFIID riid
, void **ppv
)
390 FIXME("(%p, %p, %p, %s, %p) - stub\n", This
, pidl
, pbc
, debugstr_guid(riid
), ppv
);
394 static HRESULT WINAPI
RecycleBin_BindToStorage(IShellFolder2
*This
, LPCITEMIDLIST pidl
, LPBC pbc
, REFIID riid
, void **ppv
)
396 FIXME("(%p, %p, %p, %s, %p) - stub\n", This
, pidl
, pbc
, debugstr_guid(riid
), ppv
);
400 static HRESULT WINAPI
RecycleBin_CompareIDs(IShellFolder2
*iface
, LPARAM lParam
, LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
402 RecycleBin
*This
= (RecycleBin
*)iface
;
405 TRACE("(%p, %p, %p, %p)\n", This
, (void *)lParam
, pidl1
, pidl2
);
406 if (pidl1
->mkid
.cb
!= pidl2
->mkid
.cb
)
407 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, pidl1
->mkid
.cb
- pidl2
->mkid
.cb
);
408 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (unsigned short)memcmp(pidl1
->mkid
.abID
, pidl2
->mkid
.abID
, pidl1
->mkid
.cb
));
411 static HRESULT WINAPI
RecycleBin_CreateViewObject(IShellFolder2
*iface
, HWND hwndOwner
, REFIID riid
, void **ppv
)
413 RecycleBin
*This
= (RecycleBin
*)iface
;
414 LPSHELLVIEW pShellView
;
415 HRESULT hr
= E_NOINTERFACE
;
417 TRACE("(%p, %p, %s, %p)\n", This
, hwndOwner
, debugstr_guid(riid
), ppv
);
424 if (IsEqualIID (riid
, &IID_IDropTarget
))
426 WARN ("IDropTarget not implemented\n");
429 else if (IsEqualIID (riid
, &IID_IContextMenu
) || IsEqualIID (riid
, &IID_IContextMenu2
))
431 This
->lpContextMenu2
= &recycleBincmVtblFolder
;
432 *ppv
= (void *)&This
->lpContextMenu2
;
436 else if (IsEqualIID (riid
, &IID_IShellView
))
438 pShellView
= IShellView_Constructor ((IShellFolder
*) iface
);
441 hr
= IShellView_QueryInterface (pShellView
, riid
, ppv
);
442 IShellView_Release (pShellView
);
447 TRACE ("-- (%p)->(interface=%p)\n", This
, ppv
);
452 static HRESULT WINAPI
RecycleBin_GetAttributesOf(IShellFolder2
*This
, UINT cidl
, LPCITEMIDLIST
*apidl
,
455 TRACE("(%p, %d, {%p, ...}, {%x})\n", This
, cidl
, apidl
[0], (unsigned int)*rgfInOut
);
456 *rgfInOut
&= SFGAO_CANMOVE
|SFGAO_CANDELETE
|SFGAO_HASPROPSHEET
|SFGAO_FILESYSTEM
;
460 static HRESULT WINAPI
RecycleBin_GetUIObjectOf(IShellFolder2
*iface
, HWND hwndOwner
, UINT cidl
, LPCITEMIDLIST
*apidl
,
461 REFIID riid
, UINT
*prgfInOut
, void **ppv
)
463 IUnknown
*pObj
= NULL
;
464 HRESULT hr
= E_INVALIDARG
;
465 RecycleBin
* This
= (RecycleBin
*)iface
;
467 TRACE ("(%p)->(%p,%u,apidl=%p, %p %p)\n", This
,
468 hwndOwner
, cidl
, apidl
, prgfInOut
, ppv
);
475 if ((IsEqualIID (riid
, &IID_IContextMenu
) || IsEqualIID(riid
, &IID_IContextMenu2
)) && (cidl
>= 1))
477 This
->lpContextMenu2
= &recycleBincmVtblBitbucketItem
;
478 pObj
= (IUnknown
*)(&This
->lpContextMenu2
);
479 This
->apidl
= apidl
[0];
480 IUnknown_AddRef(pObj
);
483 else if (IsEqualIID (riid
, &IID_IDropTarget
) && (cidl
>= 1))
485 hr
= IShellFolder_QueryInterface (iface
, &IID_IDropTarget
, (LPVOID
*) & pObj
);
490 if (SUCCEEDED(hr
) && !pObj
)
494 TRACE ("(%p)->hr=0x%08x\n", This
, hr
);
498 static HRESULT WINAPI
RecycleBin_GetDisplayNameOf(IShellFolder2
*This
, LPCITEMIDLIST pidl
, SHGDNF uFlags
, STRRET
*pName
)
500 PIDLRecycleStruct
*pFileDetails
;
503 TRACE("(%p, %p, %x, %p)\n", This
, pidl
, (unsigned int)uFlags
, pName
);
506 if (_ILIsBitBucket (pidl
))
510 if (HCR_GetClassNameW(&CLSID_RecycleBin
, pszPath
, MAX_PATH
))
512 pName
->uType
= STRRET_WSTR
;
513 pName
->u
.pOleStr
= StrDupW(pszPath
);
518 pFileDetails
= _ILGetRecycleStruct(pidl
);
521 pName
->u
.cStr
[0] = 0;
522 pName
->uType
= STRRET_CSTR
;
526 pFileName
= wcsrchr(pFileDetails
->szName
, L
'\\');
529 pName
->u
.cStr
[0] = 0;
530 pName
->uType
= STRRET_CSTR
;
534 pName
->u
.pOleStr
= StrDupW(pFileName
+ 1);
535 if (pName
->u
.pOleStr
== NULL
)
536 return E_OUTOFMEMORY
;
538 pName
->uType
= STRRET_WSTR
;
542 static HRESULT WINAPI
RecycleBin_SetNameOf(IShellFolder2
*This
, HWND hwnd
, LPCITEMIDLIST pidl
, LPCOLESTR pszName
,
543 SHGDNF uFlags
, LPITEMIDLIST
*ppidlOut
)
546 return E_FAIL
; /* not supported */
549 static HRESULT WINAPI
RecycleBin_GetDefaultSearchGUID(IShellFolder2
*iface
, GUID
*pguid
)
555 static HRESULT WINAPI
RecycleBin_EnumSearches(IShellFolder2
*iface
, IEnumExtraSearch
**ppEnum
)
562 static HRESULT WINAPI
RecycleBin_GetDefaultColumn(IShellFolder2
*iface
, DWORD dwReserved
, ULONG
*pSort
, ULONG
*pDisplay
)
564 RecycleBin
*This
= (RecycleBin
*)iface
;
565 TRACE("(%p, %x, %p, %p)\n", This
, (unsigned int)dwReserved
, pSort
, pDisplay
);
571 static HRESULT WINAPI
RecycleBin_GetDefaultColumnState(IShellFolder2
*iface
, UINT iColumn
, SHCOLSTATEF
*pcsFlags
)
573 RecycleBin
*This
= (RecycleBin
*)iface
;
574 TRACE("(%p, %d, %p)\n", This
, iColumn
, pcsFlags
);
575 if (iColumn
>= COLUMNS_COUNT
)
577 *pcsFlags
= RecycleBinColumns
[iColumn
].pcsFlags
;
581 static HRESULT WINAPI
RecycleBin_GetDetailsEx(IShellFolder2
*iface
, LPCITEMIDLIST pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
587 static HRESULT
FormatDateTime(LPWSTR buffer
, int size
, FILETIME
* ft
)
593 FileTimeToLocalFileTime(ft
, &lft
);
594 FileTimeToSystemTime(&lft
, &time
);
596 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &time
, NULL
, buffer
, size
);
597 if (ret
>0 && ret
<size
)
599 /* Append space + time without seconds */
601 GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &time
, NULL
, &buffer
[ret
], size
- ret
);
604 return (ret
!=0 ? E_FAIL
: S_OK
);
607 static HRESULT WINAPI
RecycleBin_GetDetailsOf(IShellFolder2
*iface
, LPCITEMIDLIST pidl
, UINT iColumn
, LPSHELLDETAILS pDetails
)
609 RecycleBin
*This
= (RecycleBin
*)iface
;
610 PIDLRecycleStruct
* pFileDetails
;
611 WCHAR buffer
[MAX_PATH
];
612 WCHAR szTypeName
[100];
616 TRACE("(%p, %p, %d, %p)\n", This
, pidl
, iColumn
, pDetails
);
617 if (iColumn
>= COLUMNS_COUNT
)
619 pDetails
->fmt
= RecycleBinColumns
[iColumn
].fmt
;
620 pDetails
->cxChar
= RecycleBinColumns
[iColumn
].cxChars
;
623 pDetails
->str
.uType
= STRRET_WSTR
;
624 LoadStringW(shell32_hInstance
, RecycleBinColumns
[iColumn
].column_name_id
, buffer
, MAX_PATH
);
625 return SHStrDupW(buffer
, &pDetails
->str
.u
.pOleStr
);
628 if (iColumn
== COLUMN_NAME
)
629 return RecycleBin_GetDisplayNameOf(iface
, pidl
, SHGDN_NORMAL
, &pDetails
->str
);
631 pFileDetails
= _ILGetRecycleStruct(pidl
);
635 FormatDateTime(buffer
, MAX_PATH
, &pFileDetails
->DeletionTime
);
638 pszBackslash
= wcsrchr(pFileDetails
->szName
, L
'\\');
639 Length
= (pszBackslash
- pFileDetails
->szName
);
640 memcpy((LPVOID
)buffer
, pFileDetails
->szName
, Length
* sizeof(WCHAR
));
641 buffer
[Length
] = L
'\0';
644 StrFormatKBSizeW(pFileDetails
->FileSize
.QuadPart
, buffer
, MAX_PATH
);
647 FormatDateTime(buffer
, MAX_PATH
, &pFileDetails
->LastModification
);
650 szTypeName
[0] = L
'\0';
651 wcscpy(buffer
,PathFindExtensionW(pFileDetails
->szName
));
652 if (!( HCR_MapTypeToValueW(buffer
, buffer
, sizeof(buffer
)/sizeof(WCHAR
), TRUE
) &&
653 HCR_MapTypeToValueW(buffer
, szTypeName
, sizeof(szTypeName
)/sizeof(WCHAR
), FALSE
)))
655 wcscpy (szTypeName
, PathFindExtensionW(pFileDetails
->szName
));
656 wcscat(szTypeName
, L
"-");
657 Length
= wcslen(szTypeName
);
658 if (LoadStringW(shell32_hInstance
, IDS_SHV_COLUMN1
, &szTypeName
[Length
], (sizeof(szTypeName
)/sizeof(WCHAR
))- Length
))
659 szTypeName
[(sizeof(szTypeName
)/sizeof(WCHAR
))-1] = L
'\0';
661 pDetails
->str
.uType
= STRRET_WSTR
;
662 return SHStrDupW(szTypeName
, &pDetails
->str
.u
.pOleStr
);
668 pDetails
->str
.uType
= STRRET_WSTR
;
669 return SHStrDupW(buffer
, &pDetails
->str
.u
.pOleStr
);
672 static HRESULT WINAPI
RecycleBin_MapColumnToSCID(IShellFolder2
*iface
, UINT iColumn
, SHCOLUMNID
*pscid
)
674 RecycleBin
*This
= (RecycleBin
*)iface
;
675 TRACE("(%p, %d, %p)\n", This
, iColumn
, pscid
);
676 if (iColumn
>=COLUMNS_COUNT
)
678 pscid
->fmtid
= *RecycleBinColumns
[iColumn
].fmtId
;
679 pscid
->pid
= RecycleBinColumns
[iColumn
].pid
;
683 static const IShellFolder2Vtbl recycleBinVtbl
=
686 RecycleBin_QueryInterface
,
691 RecycleBin_ParseDisplayName
,
692 RecycleBin_EnumObjects
,
693 RecycleBin_BindToObject
,
694 RecycleBin_BindToStorage
,
695 RecycleBin_CompareIDs
,
696 RecycleBin_CreateViewObject
,
697 RecycleBin_GetAttributesOf
,
698 RecycleBin_GetUIObjectOf
,
699 RecycleBin_GetDisplayNameOf
,
700 RecycleBin_SetNameOf
,
703 RecycleBin_GetDefaultSearchGUID
,
704 RecycleBin_EnumSearches
,
705 RecycleBin_GetDefaultColumn
,
706 RecycleBin_GetDefaultColumnState
,
707 RecycleBin_GetDetailsEx
,
708 RecycleBin_GetDetailsOf
,
709 RecycleBin_MapColumnToSCID
712 static HRESULT WINAPI
RecycleBin_IPersistFolder2_GetClassID(IPersistFolder2
*This
, CLSID
*pClassID
)
714 TRACE("(%p, %p)\n", This
, pClassID
);
715 if (This
== NULL
|| pClassID
== NULL
)
717 memcpy(pClassID
, &CLSID_RecycleBin
, sizeof(CLSID
));
721 static HRESULT WINAPI
RecycleBin_IPersistFolder2_Initialize(IPersistFolder2
*iface
, LPCITEMIDLIST pidl
)
723 RecycleBin
*This
= impl_from_IPersistFolder(iface
);
724 TRACE("(%p, %p)\n", This
, pidl
);
726 SHFree((LPVOID
)This
->pidl
);
727 This
->pidl
= ILClone(pidl
);
728 if (This
->pidl
== NULL
)
729 return E_OUTOFMEMORY
;
733 static HRESULT WINAPI
RecycleBin_IPersistFolder2_GetCurFolder(IPersistFolder2
*iface
, LPITEMIDLIST
*ppidl
)
735 RecycleBin
*This
= impl_from_IPersistFolder(iface
);
737 *ppidl
= ILClone(This
->pidl
);
741 static HRESULT WINAPI
RecycleBin_IPersistFolder2_QueryInterface(IPersistFolder2
*This
, REFIID riid
, void **ppvObject
)
743 return RecycleBin_QueryInterface((IShellFolder2
*)impl_from_IPersistFolder(This
), riid
, ppvObject
);
746 static ULONG WINAPI
RecycleBin_IPersistFolder2_AddRef(IPersistFolder2
*This
)
748 return RecycleBin_AddRef((IShellFolder2
*)impl_from_IPersistFolder(This
));
751 static ULONG WINAPI
RecycleBin_IPersistFolder2_Release(IPersistFolder2
*This
)
753 return RecycleBin_Release((IShellFolder2
*)impl_from_IPersistFolder(This
));
756 static const IPersistFolder2Vtbl recycleBinPersistVtbl
=
759 RecycleBin_IPersistFolder2_QueryInterface
,
760 RecycleBin_IPersistFolder2_AddRef
,
761 RecycleBin_IPersistFolder2_Release
,
764 RecycleBin_IPersistFolder2_GetClassID
,
766 RecycleBin_IPersistFolder2_Initialize
,
767 /* IPersistFolder2 */
768 RecycleBin_IPersistFolder2_GetCurFolder
771 /*************************************************************************
772 * BitBucket IShellExtInit interface
775 static HRESULT WINAPI
776 RecycleBin_ExtInit_QueryInterface( IShellExtInit
* iface
, REFIID riid
, void** ppvObject
)
778 return RecycleBin_QueryInterface((IShellFolder2
*)impl_from_IShellExtInit(iface
), riid
, ppvObject
);
782 RecycleBin_ExtInit_AddRef( IShellExtInit
* iface
)
784 return RecycleBin_AddRef((IShellFolder2
*)impl_from_IShellExtInit(iface
));
788 RecycleBin_ExtInit_Release( IShellExtInit
* iface
)
790 return RecycleBin_Release((IShellFolder2
*)impl_from_IShellExtInit(iface
));
793 static HRESULT WINAPI
794 RecycleBin_ExtInit_Initialize( IShellExtInit
* iface
, LPCITEMIDLIST pidlFolder
,
795 IDataObject
*pdtobj
, HKEY hkeyProgID
)
797 RecycleBin
*This
= impl_from_IShellExtInit(iface
);
799 TRACE("%p %p %p %p\n", This
, pidlFolder
, pdtobj
, hkeyProgID
);
804 static const IShellExtInitVtbl eivt
=
806 RecycleBin_ExtInit_QueryInterface
,
807 RecycleBin_ExtInit_AddRef
,
808 RecycleBin_ExtInit_Release
,
809 RecycleBin_ExtInit_Initialize
813 /*************************************************************************
814 * BitBucket context menu
818 static HRESULT WINAPI
819 RecycleBin_IContextMenu2Folder_QueryInterface( IContextMenu2
* iface
, REFIID riid
, void** ppvObject
)
821 return RecycleBin_QueryInterface((IShellFolder2
*)impl_from_IContextMenu2(iface
), riid
, ppvObject
);
825 RecycleBin_IContextMenu2Folder_AddRef( IContextMenu2
* iface
)
827 return RecycleBin_AddRef((IShellFolder2
*)impl_from_IContextMenu2(iface
));
831 RecycleBin_IContextMenu2Folder_Release( IContextMenu2
* iface
)
833 return RecycleBin_Release((IShellFolder2
*)impl_from_IContextMenu2(iface
));
836 static HRESULT WINAPI
837 RecycleBin_IContextMenu2Folder_QueryContextMenu( IContextMenu2
* iface
, HMENU hmenu
, UINT indexMenu
,
838 UINT idCmdFirst
, UINT idCmdLast
, UINT uFlags
)
843 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
845 TRACE("%p %p %u %u %u %u\n", This
,
846 hmenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
851 memset( &mii
, 0, sizeof(mii
) );
852 mii
.cbSize
= sizeof(mii
);
853 mii
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
854 mii
.fState
= MFS_ENABLED
;
856 LoadStringW(shell32_hInstance
, IDS_EMPTY_BITBUCKET
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
));
857 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
858 mii
.dwTypeData
= szBuffer
;
859 mii
.cch
= wcslen( mii
.dwTypeData
);
860 mii
.wID
= idCmdFirst
+ id
++;
861 mii
.fType
= MFT_STRING
;
864 if (!InsertMenuItemW( hmenu
, indexMenu
, TRUE
, &mii
))
867 return MAKE_HRESULT( SEVERITY_SUCCESS
, 0, id
);
870 static HRESULT WINAPI
871 RecycleBin_IContextMenu2Folder_InvokeCommand( IContextMenu2
* iface
, LPCMINVOKECOMMANDINFO lpici
)
875 LPSHELLVIEW lpSV
= NULL
;
876 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
878 TRACE("%p %p verb %p\n", This
, lpici
, lpici
->lpVerb
);
880 if ( LOWORD(lpici
->lpVerb
) == This
->iIdEmpty
)
884 hr
= SHEmptyRecycleBinW(lpici
->hwnd
, L
"C:\\", 0);
885 TRACE("result %x\n", hr
);
891 if((lpSB
= (LPSHELLBROWSER
)SendMessageA(lpici
->hwnd
, CWM_GETISHELLBROWSER
,0,0)))
893 if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
)))
895 IShellView_Refresh(lpSV
);
902 static HRESULT WINAPI
903 RecycleBin_IContextMenu2Folder_GetCommandString( IContextMenu2
* iface
, UINT_PTR idCmd
, UINT uType
,
904 UINT
* pwReserved
, LPSTR pszName
, UINT cchMax
)
906 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
908 FIXME("%p %lu %u %p %p %u\n", This
,
909 idCmd
, uType
, pwReserved
, pszName
, cchMax
);
914 /**************************************************************************
915 * RecycleBin_IContextMenu2Item_HandleMenuMsg()
917 static HRESULT WINAPI
RecycleBin_IContextMenu2Folder_HandleMenuMsg(
918 IContextMenu2
*iface
,
923 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
925 TRACE("RecycleBin_IContextMenu2Item_IContextMenu2Folder_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n",This
, uMsg
, wParam
, lParam
);
931 static const IContextMenu2Vtbl recycleBincmVtblFolder
=
933 RecycleBin_IContextMenu2Folder_QueryInterface
,
934 RecycleBin_IContextMenu2Folder_AddRef
,
935 RecycleBin_IContextMenu2Folder_Release
,
936 RecycleBin_IContextMenu2Folder_QueryContextMenu
,
937 RecycleBin_IContextMenu2Folder_InvokeCommand
,
938 RecycleBin_IContextMenu2Folder_GetCommandString
,
939 RecycleBin_IContextMenu2Folder_HandleMenuMsg
943 /**************************************************************************
944 * IContextMenu2 Bitbucket Item Implementation
947 /************************************************************************
948 * RecycleBin_IContextMenu2Item_QueryInterface
950 static HRESULT WINAPI
RecycleBin_IContextMenu2Item_QueryInterface(IContextMenu2
* iface
, REFIID iid
, LPVOID
* ppvObject
)
952 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
954 TRACE("(%p)\n", This
);
956 return RecycleBin_QueryInterface((IShellFolder2
*)This
, iid
, ppvObject
);
959 /************************************************************************
960 * RecycleBin_IContextMenu2Item_AddRef
962 static ULONG WINAPI
RecycleBin_IContextMenu2Item_AddRef(IContextMenu2
* iface
)
964 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
966 TRACE("(%p)->(count=%u)\n", This
, This
->refCount
);
968 return RecycleBin_AddRef((IShellFolder2
*)This
);
971 /************************************************************************
972 * RecycleBin_IContextMenu2Item_Release
974 static ULONG WINAPI
RecycleBin_IContextMenu2Item_Release(IContextMenu2
* iface
)
976 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
978 TRACE("(%p)->(count=%u)\n", This
, This
->refCount
);
980 return RecycleBin_Release((IShellFolder2
*)This
);
983 /**************************************************************************
984 * RecycleBin_IContextMenu2Item_QueryContextMenu()
986 static HRESULT WINAPI
RecycleBin_IContextMenu2Item_QueryContextMenu(
987 IContextMenu2
*iface
,
994 WCHAR szBuffer
[30] = {0};
997 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
999 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
1000 This
, hMenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
1002 if (LoadStringW(shell32_hInstance
, IDS_RESTORE
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
1004 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
1005 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
, MFT_STRING
, szBuffer
, MFS_ENABLED
);
1009 if (LoadStringW(shell32_hInstance
, IDS_CUT
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
1011 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
++, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
1012 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
1013 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
++, MFT_STRING
, szBuffer
, MFS_ENABLED
);
1016 if (LoadStringW(shell32_hInstance
, IDS_DELETE
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
1018 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
1019 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
++, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
1020 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
++, MFT_STRING
, szBuffer
, MFS_ENABLED
);
1023 if (LoadStringW(shell32_hInstance
, IDS_PROPERTIES
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
1025 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
1026 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
++, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
1027 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
, MFT_STRING
, szBuffer
, MFS_DEFAULT
);
1030 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, Count
);
1034 /**************************************************************************
1035 * RecycleBin_IContextMenu2Item_InvokeCommand()
1037 static HRESULT WINAPI
RecycleBin_IContextMenu2Item_InvokeCommand(
1038 IContextMenu2
*iface
,
1039 LPCMINVOKECOMMANDINFO lpcmi
)
1042 SEARCH_CONTEXT Context
;
1043 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
1044 static LPCWSTR szDrive
= L
"C:\\";
1046 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This
,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
1048 if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(1) || lpcmi
->lpVerb
== MAKEINTRESOURCEA(5))
1050 Context
.pFileDetails
= _ILGetRecycleStruct(This
->apidl
);
1051 Context
.bFound
= FALSE
;
1053 EnumerateRecycleBinW(szDrive
, CBSearchBitBucket
, (PVOID
)&Context
);
1054 if (!Context
.bFound
)
1057 if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(1))
1060 if (RestoreFile(Context
.hDeletedFile
))
1067 DeleteFileHandleToRecycleBin(Context
.hDeletedFile
);
1071 else if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(3))
1073 FIXME("implement cut\n");
1076 else if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(7))
1078 FIXME("implement properties\n");
1085 /**************************************************************************
1086 * RecycleBin_IContextMenu2Item_GetCommandString()
1089 static HRESULT WINAPI
RecycleBin_IContextMenu2Item_GetCommandString(
1090 IContextMenu2
*iface
,
1097 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
1099 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This
, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
1107 /**************************************************************************
1108 * RecycleBin_IContextMenu2Item_HandleMenuMsg()
1110 static HRESULT WINAPI
RecycleBin_IContextMenu2Item_HandleMenuMsg(
1111 IContextMenu2
*iface
,
1116 RecycleBin
* This
= impl_from_IContextMenu2(iface
);
1118 TRACE("RecycleBin_IContextMenu2Item_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n",This
, uMsg
, wParam
, lParam
);
1123 static const IContextMenu2Vtbl recycleBincmVtblBitbucketItem
=
1125 RecycleBin_IContextMenu2Item_QueryInterface
,
1126 RecycleBin_IContextMenu2Item_AddRef
,
1127 RecycleBin_IContextMenu2Item_Release
,
1128 RecycleBin_IContextMenu2Item_QueryContextMenu
,
1129 RecycleBin_IContextMenu2Item_InvokeCommand
,
1130 RecycleBin_IContextMenu2Item_GetCommandString
,
1131 RecycleBin_IContextMenu2Item_HandleMenuMsg
1135 void toggleNukeOnDeleteOption(HWND hwndDlg
, BOOL bEnable
)
1139 SendDlgItemMessage(hwndDlg
, 14001, BM_SETCHECK
, BST_UNCHECKED
, 0);
1140 EnableWindow(GetDlgItem(hwndDlg
, 14002), FALSE
);
1141 SendDlgItemMessage(hwndDlg
, 14003, BM_SETCHECK
, BST_CHECKED
, 0);
1145 SendDlgItemMessage(hwndDlg
, 14001, BM_SETCHECK
, BST_CHECKED
, 0);
1146 EnableWindow(GetDlgItem(hwndDlg
, 14002), TRUE
);
1147 SendDlgItemMessage(hwndDlg
, 14003, BM_SETCHECK
, BST_UNCHECKED
, 0);
1153 InitializeBitBucketDlg(HWND hwndDlg
, WCHAR DefaultDrive
)
1155 WCHAR CurDrive
= L
'A';
1156 WCHAR szDrive
[] = L
"A:\\";
1159 WCHAR szVolume
[100];
1160 DWORD MaxComponent
, Flags
;
1166 ULARGE_INTEGER TotalNumberOfFreeBytes
, TotalNumberOfBytes
, FreeBytesAvailable
;
1171 PDRIVE_ITEM_CONTEXT pItem
= NULL
, pDefault
= NULL
, pFirst
= NULL
;
1173 hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
1175 if (!LoadStringW(shell32_hInstance
, IDS_RECYCLEBIN_LOCATION
, szVolume
, sizeof(szVolume
) / sizeof(WCHAR
)))
1178 GetClientRect(hDlgCtrl
, &rect
);
1180 memset(&lc
, 0, sizeof(LV_COLUMN
) );
1181 lc
.mask
= LVCF_WIDTH
| LVCF_TEXT
| LVCF_SUBITEM
| LVCF_FMT
;
1183 columnSize
= 140; //FIXME
1185 lc
.fmt
= LVCFMT_FIXED_WIDTH
;
1187 lc
.cchTextMax
= wcslen(szVolume
);
1188 lc
.pszText
= szVolume
;
1189 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&lc
);
1191 if (!LoadStringW(shell32_hInstance
, IDS_RECYCLEBIN_DISKSPACE
, szVolume
, sizeof(szVolume
) / sizeof(WCHAR
)))
1195 lc
.cx
= rect
.right
- rect
.left
- columnSize
;
1196 lc
.cchTextMax
= wcslen(szVolume
);
1197 lc
.pszText
= szVolume
;
1198 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&lc
);
1200 dwDrives
= GetLogicalDrives();
1204 if ((dwDrives
& 0x1))
1206 UINT Type
= GetDriveTypeW(szDrive
);
1207 if (Type
== DRIVE_FIXED
) //FIXME
1209 if (!GetVolumeInformationW(szDrive
, szName
, sizeof(szName
) / sizeof(WCHAR
), &dwSerial
, &MaxComponent
, &Flags
, NULL
, 0))
1215 swprintf(szVolume
, L
"%s (%c)", szName
, szDrive
[0]);
1216 memset(&li
, 0x0, sizeof(LVITEMW
));
1217 li
.mask
= LVIF_TEXT
| LVIF_PARAM
;
1219 li
.pszText
= szVolume
;
1220 li
.iItem
= itemCount
;
1221 (void)SendMessageW(hDlgCtrl
, LVM_INSERTITEMW
, 0, (LPARAM
)&li
);
1222 if (GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailable
, &TotalNumberOfBytes
, &TotalNumberOfFreeBytes
))
1224 if (StrFormatByteSizeW(TotalNumberOfFreeBytes
.QuadPart
, szVolume
, sizeof(szVolume
) / sizeof(WCHAR
)))
1227 pItem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DRIVE_ITEM_CONTEXT
));
1230 swprintf(szName
, L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\%04X-%04X", LOWORD(dwSerial
), HIWORD(dwSerial
));
1231 dwSize
= sizeof(DWORD
);
1232 RegGetValueW(HKEY_CURRENT_USER
, szName
, L
"MaxCapacity", RRF_RT_DWORD
, NULL
, &pItem
->dwMaxCapacity
, &dwSize
);
1233 dwSize
= sizeof(DWORD
);
1234 RegGetValueW(HKEY_CURRENT_USER
, szName
, L
"NukeOnDelete", RRF_RT_DWORD
, NULL
, &pItem
->dwNukeOnDelete
, &dwSize
);
1235 pItem
->dwSerial
= dwSerial
;
1236 li
.mask
= LVIF_PARAM
;
1237 li
.lParam
= (LPARAM
)pItem
;
1238 (void)SendMessageW(hDlgCtrl
, LVM_SETITEMW
, 0, (LPARAM
)&li
);
1239 if (CurDrive
== DefaultDrive
)
1241 defIndex
= itemCount
;
1248 li
.mask
= LVIF_TEXT
;
1250 li
.pszText
= szVolume
;
1251 li
.iItem
= itemCount
;
1252 (void)SendMessageW(hDlgCtrl
, LVM_SETITEMW
, 0, (LPARAM
)&li
);
1259 szDrive
[0] = CurDrive
;
1260 dwDrives
= (dwDrives
>> 1);
1267 toggleNukeOnDeleteOption(hwndDlg
, pDefault
->dwNukeOnDelete
);
1268 SetDlgItemInt(hwndDlg
, 14002, pDefault
->dwMaxCapacity
, FALSE
);
1270 ZeroMemory(&li
, sizeof(li
));
1271 li
.mask
= LVIF_STATE
;
1272 li
.stateMask
= (UINT
)-1;
1273 li
.state
= LVIS_FOCUSED
|LVIS_SELECTED
;
1274 li
.iItem
= defIndex
;
1275 (void)SendMessageW(hDlgCtrl
, LVM_SETITEMW
, 0, (LPARAM
)&li
);
1279 static BOOL
StoreDriveSettings(HWND hwndDlg
)
1282 HWND hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
1284 PDRIVE_ITEM_CONTEXT pItem
;
1290 if (RegCreateKeyExW(HKEY_CURRENT_USER
, L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume", 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
1293 iCount
= ListView_GetItemCount(hDlgCtrl
);
1295 ZeroMemory(&li
, sizeof(li
));
1296 li
.mask
= LVIF_PARAM
;
1298 for(iIndex
= 0; iIndex
< iCount
; iIndex
++)
1301 if (SendMessageW(hDlgCtrl
, LVM_GETITEMW
, 0, (LPARAM
)&li
))
1303 pItem
= (PDRIVE_ITEM_CONTEXT
)li
.lParam
;
1304 swprintf(szSerial
, L
"%04X-%04X", LOWORD(pItem
->dwSerial
), HIWORD(pItem
->dwSerial
));
1305 if (RegCreateKeyExW(hKey
, szSerial
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hSubKey
, NULL
) == ERROR_SUCCESS
)
1307 dwSize
= sizeof(DWORD
);
1308 RegSetValueExW(hSubKey
, L
"NukeOnDelete", 0, REG_DWORD
, (LPVOID
)&pItem
->dwNukeOnDelete
, dwSize
);
1309 dwSize
= sizeof(DWORD
);
1310 RegSetValueExW(hSubKey
, L
"MaxCapacity", 0, REG_DWORD
, (LPVOID
)&pItem
->dwMaxCapacity
, dwSize
);
1311 RegCloseKey(hSubKey
);
1320 static VOID
FreeDriveItemContext(HWND hwndDlg
)
1323 HWND hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
1326 iCount
= ListView_GetItemCount(hDlgCtrl
);
1328 ZeroMemory(&li
, sizeof(li
));
1329 li
.mask
= LVIF_PARAM
;
1331 for(iIndex
= 0; iIndex
< iCount
; iIndex
++)
1334 if (SendMessageW(hDlgCtrl
, LVM_GETITEMW
, 0, (LPARAM
)&li
))
1336 HeapFree(GetProcessHeap(), 0, (LPVOID
)li
.lParam
);
1342 GetDefaultItem(HWND hwndDlg
, LVITEMW
* li
)
1345 UINT iItemCount
, iIndex
;
1347 hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
1351 iItemCount
= ListView_GetItemCount(hDlgCtrl
);
1355 ZeroMemory(li
, sizeof(LVITEMW
));
1356 li
->mask
= LVIF_PARAM
| LVIF_STATE
;
1357 li
->stateMask
= (UINT
)-1;
1358 for (iIndex
= 0; iIndex
< iItemCount
; iIndex
++)
1361 if (SendMessageW(hDlgCtrl
, LVM_GETITEMW
, 0, (LPARAM
)li
))
1363 if (li
->state
& LVIS_SELECTED
)
1383 PDRIVE_ITEM_CONTEXT pItem
;
1386 PROPSHEETPAGE
* page
;
1392 page
= (PROPSHEETPAGE
*)lParam
;
1393 InitializeBitBucketDlg(hwndDlg
, (WCHAR
)page
->lParam
);
1394 dwStyle
= (DWORD
) SendDlgItemMessage(hwndDlg
, 14000, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
1395 dwStyle
= dwStyle
| LVS_EX_FULLROWSELECT
;
1396 SendDlgItemMessage(hwndDlg
, 14000, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, dwStyle
);
1397 if (GetDlgCtrlID((HWND
)wParam
) != 14000)
1399 SetFocus(GetDlgItem(hwndDlg
, 14000));
1404 switch(LOWORD(wParam
))
1407 toggleNukeOnDeleteOption(hwndDlg
, FALSE
);
1408 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1411 toggleNukeOnDeleteOption(hwndDlg
, TRUE
);
1412 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1415 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1420 lppsn
= (LPPSHNOTIFY
) lParam
;
1421 lppl
= (LPNMLISTVIEW
) lParam
;
1422 if (lppsn
->hdr
.code
== PSN_APPLY
)
1424 if (GetDefaultItem(hwndDlg
, &li
) > -1)
1426 pItem
= (PDRIVE_ITEM_CONTEXT
)li
.lParam
;
1429 uResult
= GetDlgItemInt(hwndDlg
, 14002, &bSuccess
, FALSE
);
1431 pItem
->dwMaxCapacity
= uResult
;
1432 if (SendDlgItemMessageW(hwndDlg
, 14003, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
1433 pItem
->dwNukeOnDelete
= TRUE
;
1435 pItem
->dwNukeOnDelete
= FALSE
;
1438 if (StoreDriveSettings(hwndDlg
))
1440 SetWindowLongPtr( hwndDlg
, DWL_MSGRESULT
, PSNRET_NOERROR
);
1444 else if (lppl
->hdr
.code
== LVN_ITEMCHANGING
)
1446 ZeroMemory(&li
, sizeof(li
));
1447 li
.mask
= LVIF_PARAM
;
1448 li
.iItem
= lppl
->iItem
;
1449 if (!SendMessageW(lppl
->hdr
.hwndFrom
, LVM_GETITEMW
, 0, (LPARAM
)&li
))
1452 pItem
= (PDRIVE_ITEM_CONTEXT
)li
.lParam
;
1456 if (!(lppl
->uOldState
& LVIS_FOCUSED
) && (lppl
->uNewState
& LVIS_FOCUSED
))
1458 /* new focused item */
1459 toggleNukeOnDeleteOption(lppl
->hdr
.hwndFrom
, pItem
->dwNukeOnDelete
);
1460 SetDlgItemInt(hwndDlg
, 14002, pItem
->dwMaxCapacity
, FALSE
);
1462 else if ((lppl
->uOldState
& LVIS_FOCUSED
) && !(lppl
->uNewState
& LVIS_FOCUSED
))
1465 uResult
= GetDlgItemInt(hwndDlg
, 14002, &bSuccess
, FALSE
);
1467 pItem
->dwMaxCapacity
= uResult
;
1468 if (SendDlgItemMessageW(hwndDlg
, 14003, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
1469 pItem
->dwNukeOnDelete
= TRUE
;
1471 pItem
->dwNukeOnDelete
= FALSE
;
1478 FreeDriveItemContext(hwndDlg
);
1484 BOOL
SH_ShowRecycleBinProperties(WCHAR sDrive
)
1486 HPROPSHEETPAGE hpsp
[1];
1487 PROPSHEETHEADERW psh
;
1488 HPROPSHEETPAGE hprop
;
1493 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
1494 psh
.dwSize
= sizeof(PROPSHEETHEADERW
);
1495 psh
.dwFlags
= PSP_DEFAULT
| PSH_PROPTITLE
;
1496 psh
.pszCaption
= MAKEINTRESOURCEW(IDS_RECYCLEBIN_FOLDER_NAME
);
1497 psh
.hwndParent
= NULL
;
1498 psh
.u3
.phpage
= hpsp
;
1499 psh
.hInstance
= shell32_hInstance
;
1501 hprop
= SH_CreatePropertySheetPage("BITBUCKET_PROPERTIES_DLG", BitBucketDlg
, (LPARAM
)sDrive
, NULL
);
1504 ERR("Failed to create property sheet\n");
1507 hpsp
[psh
.nPages
] = hprop
;
1511 ret
= PropertySheetW(&psh
);
1519 TRASH_CanTrashFile(LPCWSTR wszPath
)
1522 DWORD dwNukeOnDelete
, dwType
, VolSerialNumber
, MaxComponentLength
;
1523 DWORD FileSystemFlags
, dwSize
, dwDisposition
;
1526 WCHAR szKey
[150] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\";
1528 if (wszPath
[1] != L
':')
1534 if (GetDriveTypeW(wszPath
) != DRIVE_FIXED
)
1536 /* no bitbucket on removable media */
1540 if (!GetVolumeInformationW(wszPath
, NULL
, 0, &VolSerialNumber
, &MaxComponentLength
, &FileSystemFlags
, NULL
, 0))
1542 ERR("GetVolumeInformationW failed with %u\n", GetLastError());
1546 swprintf(szBuffer
, L
"%04X-%04X", LOWORD(VolSerialNumber
), HIWORD(VolSerialNumber
));
1547 wcscat(szKey
, szBuffer
);
1549 if (RegCreateKeyExW(HKEY_CURRENT_USER
, szKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, &dwDisposition
) != ERROR_SUCCESS
)
1551 ERR("RegCreateKeyExW failed\n");
1555 if (dwDisposition
& REG_CREATED_NEW_KEY
)
1557 /* per default move to bitbucket */
1559 RegSetValueExW(hKey
, L
"NukeOnDelete", 0, REG_DWORD
, (LPBYTE
)&dwNukeOnDelete
, sizeof(DWORD
));
1560 /* per default unlimited size */
1562 RegSetValueExW(hKey
, L
"MaxCapacity", 0, REG_DWORD
, (LPBYTE
)&dwSize
, sizeof(DWORD
));
1568 dwSize
= sizeof(dwNukeOnDelete
);
1569 ret
= RegQueryValueExW(hKey
, L
"NukeOnDelete", NULL
, &dwType
, (LPBYTE
)&dwNukeOnDelete
, &dwSize
);
1570 if (ret
!= ERROR_SUCCESS
)
1572 if (ret
== ERROR_FILE_NOT_FOUND
)
1574 /* restore key and enable bitbucket */
1576 RegSetValueExW(hKey
, L
"NukeOnDelete", 0, REG_DWORD
, (LPBYTE
)&dwNukeOnDelete
, sizeof(DWORD
));
1581 else if (dwNukeOnDelete
)
1583 /* do not delete to bitbucket */
1588 * check if bitbucket is full
1596 TRASH_TrashFile(LPCWSTR wszPath
)
1598 TRACE("(%s)\n", debugstr_w(wszPath
));
1599 return DeleteFileToRecycleBinW(wszPath
);
1602 /*************************************************************************
1603 * SHUpdateRecycleBinIcon [SHELL32.@]
1607 HRESULT WINAPI
SHUpdateRecycleBinIcon(void)