2 * Trash virtual folder support. The trashing engine is implemented in trash.c
4 * Copyright (C) 2006 Mikolaj Zalewski
5 * Copyright (C) 2009 Andrew Hill
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 #define MAX_PROPERTY_SHEET_PAGE 32
26 WINE_DEFAULT_DEBUG_CHANNEL(CBitBucket
);
38 static const columninfo CBitBucketColumns
[] =
40 {IDS_SHV_COLUMN1
, &FMTID_Storage
, PID_STG_NAME
, SHCOLSTATE_TYPE_STR
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 30},
41 {IDS_SHV_COLUMN_DELFROM
, &FMTID_Displaced
, PID_DISPLACED_FROM
, SHCOLSTATE_TYPE_STR
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 30},
42 {IDS_SHV_COLUMN_DELDATE
, &FMTID_Displaced
, PID_DISPLACED_DATE
, SHCOLSTATE_TYPE_DATE
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 20},
43 {IDS_SHV_COLUMN2
, &FMTID_Storage
, PID_STG_SIZE
, SHCOLSTATE_TYPE_INT
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 20},
44 {IDS_SHV_COLUMN3
, &FMTID_Storage
, PID_STG_STORAGETYPE
,SHCOLSTATE_TYPE_INT
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 20},
45 {IDS_SHV_COLUMN4
, &FMTID_Storage
, PID_STG_WRITETIME
, SHCOLSTATE_TYPE_DATE
|SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 20},
46 /* {"creation time", &FMTID_Storage, PID_STG_CREATETIME, SHCOLSTATE_TYPE_DATE, LVCFMT_LEFT, 20}, */
47 /* {"attribs", &FMTID_Storage, PID_STG_ATTRIBUTES, SHCOLSTATE_TYPE_STR, LVCFMT_LEFT, 20}, */
51 #define COLUMN_DELFROM 1
52 #define COLUMN_DATEDEL 2
55 #define COLUMN_MTIME 5
57 #define COLUMNS_COUNT 6
63 class CBitBucketEnum
:
64 public IEnumIDListImpl
70 HRESULT WINAPI
Initialize(DWORD dwFlags
);
71 static BOOL WINAPI
CBEnumBitBucket(IN PVOID Context
, IN HANDLE hDeletedFile
);
72 BOOL WINAPI
CBEnumBitBucket(IN HANDLE hDeletedFile
);
74 BEGIN_COM_MAP(CBitBucketEnum
)
75 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
79 class CCBitBucketBackgroundContextMenu
:
80 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
86 CCBitBucketBackgroundContextMenu();
87 ~CCBitBucketBackgroundContextMenu();
90 virtual HRESULT WINAPI
QueryContextMenu(HMENU hMenu
, UINT indexMenu
, UINT idCmdFirst
, UINT idCmdLast
, UINT uFlags
);
91 virtual HRESULT WINAPI
InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi
);
92 virtual HRESULT WINAPI
GetCommandString(UINT_PTR idCommand
,UINT uFlags
, UINT
*lpReserved
, LPSTR lpszName
, UINT uMaxNameLen
);
95 virtual HRESULT WINAPI
HandleMenuMsg(UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
97 BEGIN_COM_MAP(CCBitBucketBackgroundContextMenu
)
98 COM_INTERFACE_ENTRY_IID(IID_IContextMenu
, IContextMenu
)
99 COM_INTERFACE_ENTRY_IID(IID_IContextMenu2
, IContextMenu2
)
103 class CCBitBucketItemContextMenu
:
104 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
110 CCBitBucketItemContextMenu();
111 ~CCBitBucketItemContextMenu();
112 HRESULT WINAPI
Initialize(LPCITEMIDLIST pidl
);
115 virtual HRESULT WINAPI
QueryContextMenu(HMENU hMenu
, UINT indexMenu
, UINT idCmdFirst
, UINT idCmdLast
, UINT uFlags
);
116 virtual HRESULT WINAPI
InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi
);
117 virtual HRESULT WINAPI
GetCommandString(UINT_PTR idCommand
,UINT uFlags
, UINT
*lpReserved
, LPSTR lpszName
, UINT uMaxNameLen
);
120 virtual HRESULT WINAPI
HandleMenuMsg(UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
122 BEGIN_COM_MAP(CCBitBucketItemContextMenu
)
123 COM_INTERFACE_ENTRY_IID(IID_IContextMenu
, IContextMenu
)
124 COM_INTERFACE_ENTRY_IID(IID_IContextMenu2
, IContextMenu2
)
130 PIDLRecycleStruct
*pFileDetails
;
133 }SEARCH_CONTEXT
, *PSEARCH_CONTEXT
;
137 DWORD dwNukeOnDelete
;
140 }DRIVE_ITEM_CONTEXT
, *PDRIVE_ITEM_CONTEXT
;
142 BOOL WINAPI
CBSearchBitBucket(IN PVOID Context
, IN HANDLE hDeletedFile
)
144 PSEARCH_CONTEXT pContext
= (PSEARCH_CONTEXT
)Context
;
146 PDELETED_FILE_DETAILS_W pFileDetails
;
150 if (!GetDeletedFileDetailsW(hDeletedFile
,
154 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
156 ERR("GetDeletedFileDetailsW failed\n");
160 pFileDetails
= (DELETED_FILE_DETAILS_W
*)SHAlloc(dwSize
);
167 if (!GetDeletedFileDetailsW(hDeletedFile
,
172 ERR("GetDeletedFileDetailsW failed\n");
173 SHFree(pFileDetails
);
177 ret
= memcmp(pFileDetails
, pContext
->pFileDetails
, dwSize
);
180 pContext
->hDeletedFile
= hDeletedFile
;
181 pContext
->bFound
= TRUE
;
184 CloseRecycleBinHandle(hDeletedFile
);
186 SHFree(pFileDetails
);
190 static PIDLRecycleStruct
* _ILGetRecycleStruct(LPCITEMIDLIST pidl
)
192 LPPIDLDATA pdata
= _ILGetDataPointer(pidl
);
194 if (pdata
&& pdata
->type
==0x00)
195 return (PIDLRecycleStruct
*)&(pdata
->u
.crecycle
);
200 CBitBucketEnum::CBitBucketEnum()
204 CBitBucketEnum::~CBitBucketEnum()
208 HRESULT WINAPI
CBitBucketEnum::Initialize(DWORD dwFlags
)
210 static LPCWSTR szDrive
= L
"C:\\";
212 if (dwFlags
& SHCONTF_NONFOLDERS
)
214 TRACE("Starting Enumeration\n");
216 if (!EnumerateRecycleBinW(szDrive
/* FIXME */ , CBEnumBitBucket
, (PVOID
)this))
218 WARN("Error: EnumerateCBitBucketW failed\n");
229 static LPITEMIDLIST
_ILCreateRecycleItem(PDELETED_FILE_DETAILS_W pFileDetails
)
233 PIDLRecycleStruct
* p
;
234 int size0
= (char*)&tmp
.u
.crecycle
.szName
-(char*)&tmp
.u
.crecycle
;
238 size
+= (wcslen(pFileDetails
->FileName
) + 1) * sizeof(WCHAR
);
240 pidl
= (LPITEMIDLIST
)SHAlloc(size
+ 4);
244 pidl
->mkid
.cb
= size
+2;
245 memcpy(pidl
->mkid
.abID
, &tmp
, 2+size0
);
247 p
= &((PIDLDATA
*)pidl
->mkid
.abID
)->u
.crecycle
;
248 RtlCopyMemory(p
, pFileDetails
, sizeof(DELETED_FILE_DETAILS_W
));
249 wcscpy(p
->szName
, pFileDetails
->FileName
);
250 *(WORD
*)((char*)pidl
+(size
+2)) = 0;
254 BOOL WINAPI
CBitBucketEnum::CBEnumBitBucket(IN PVOID Context
, IN HANDLE hDeletedFile
)
256 return ((CBitBucketEnum
*)Context
)->CBEnumBitBucket(hDeletedFile
);
259 BOOL WINAPI
CBitBucketEnum::CBEnumBitBucket(IN HANDLE hDeletedFile
)
261 PDELETED_FILE_DETAILS_W pFileDetails
;
263 LPITEMIDLIST pidl
= NULL
;
266 if (!GetDeletedFileDetailsW(hDeletedFile
,
270 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
272 ERR("GetDeletedFileDetailsW failed\n");
276 pFileDetails
= (DELETED_FILE_DETAILS_W
*)SHAlloc(dwSize
);
283 if (!GetDeletedFileDetailsW(hDeletedFile
,
288 ERR("GetDeletedFileDetailsW failed\n");
289 SHFree(pFileDetails
);
293 pidl
= _ILCreateRecycleItem(pFileDetails
);
296 SHFree(pFileDetails
);
300 ret
= AddToEnumList(pidl
);
304 SHFree(pFileDetails
);
305 TRACE("Returning %d\n", ret
);
306 CloseRecycleBinHandle(hDeletedFile
);
310 /*************************************************************************
311 * BitBucket context menu
315 CCBitBucketBackgroundContextMenu::CCBitBucketBackgroundContextMenu()
320 CCBitBucketBackgroundContextMenu::~CCBitBucketBackgroundContextMenu()
324 HRESULT WINAPI
CCBitBucketBackgroundContextMenu::QueryContextMenu(HMENU hMenu
, UINT indexMenu
, UINT idCmdFirst
, UINT idCmdLast
, UINT uFlags
)
330 TRACE("%p %p %u %u %u %u\n", this, hMenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
335 memset(&mii
, 0, sizeof(mii
));
336 mii
.cbSize
= sizeof(mii
);
337 mii
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
338 mii
.fState
= MFS_ENABLED
;
340 LoadStringW(shell32_hInstance
, IDS_EMPTY_BITBUCKET
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
));
341 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
342 mii
.dwTypeData
= szBuffer
;
343 mii
.cch
= wcslen( mii
.dwTypeData
);
344 mii
.wID
= idCmdFirst
+ id
++;
345 mii
.fType
= MFT_STRING
;
348 if (!InsertMenuItemW(hMenu
, indexMenu
, TRUE
, &mii
))
351 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, id
);
354 HRESULT WINAPI
CCBitBucketBackgroundContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi
)
358 LPSHELLVIEW lpSV
= NULL
;
360 TRACE("%p %p verb %p\n", this, lpcmi
, lpcmi
->lpVerb
);
362 if (LOWORD(lpcmi
->lpVerb
) == iIdEmpty
)
366 hr
= SHEmptyRecycleBinW(lpcmi
->hwnd
, L
"C:\\", 0);
367 TRACE("result %x\n", hr
);
371 lpSB
= (LPSHELLBROWSER
)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
, 0, 0);
372 if (lpSB
&& SUCCEEDED(lpSB
->QueryActiveShellView(&lpSV
)))
378 HRESULT WINAPI
CCBitBucketBackgroundContextMenu::GetCommandString(UINT_PTR idCommand
, UINT uFlags
, UINT
*lpReserved
, LPSTR lpszName
, UINT uMaxNameLen
)
380 FIXME("%p %lu %u %p %p %u\n", this, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
385 HRESULT WINAPI
CCBitBucketBackgroundContextMenu::HandleMenuMsg(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
387 TRACE("CBitBucket_IContextMenu2Item_IContextMenu2Folder_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg
, wParam
, lParam
);
392 static HRESULT WINAPI
CBitBucketBackgroundContextMenuConstructor(REFIID riid
, LPVOID
*ppv
)
394 CComObject
<CCBitBucketBackgroundContextMenu
> *theMenu
;
395 CComPtr
<IUnknown
> result
;
398 TRACE("%s\n", shdebugstr_guid(&riid
));
403 ATLTRY(theMenu
= new CComObject
<CCBitBucketBackgroundContextMenu
>);
405 return E_OUTOFMEMORY
;
406 hResult
= theMenu
->QueryInterface(riid
, (void **)&result
);
412 *ppv
= result
.Detach();
413 TRACE ("--(%p)\n", *ppv
);
417 /**************************************************************************
418 * IContextMenu2 Bitbucket Item Implementation
421 CCBitBucketItemContextMenu::CCBitBucketItemContextMenu()
426 CCBitBucketItemContextMenu::~CCBitBucketItemContextMenu()
431 HRESULT WINAPI
CCBitBucketItemContextMenu::Initialize(LPCITEMIDLIST pidl
)
433 apidl
= ILClone(pidl
);
435 return E_OUTOFMEMORY
;
439 HRESULT WINAPI
CCBitBucketItemContextMenu::QueryContextMenu(HMENU hMenu
, UINT indexMenu
, UINT idCmdFirst
, UINT idCmdLast
, UINT uFlags
)
441 WCHAR szBuffer
[30] = {0};
444 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n", this, hMenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
446 if (LoadStringW(shell32_hInstance
, IDS_RESTORE
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
448 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
449 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
, MFT_STRING
, szBuffer
, MFS_ENABLED
);
453 if (LoadStringW(shell32_hInstance
, IDS_CUT
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
455 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
++, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
456 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
457 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
++, MFT_STRING
, szBuffer
, MFS_ENABLED
);
460 if (LoadStringW(shell32_hInstance
, IDS_DELETE
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
462 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
463 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
++, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
464 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
++, MFT_STRING
, szBuffer
, MFS_ENABLED
);
467 if (LoadStringW(shell32_hInstance
, IDS_PROPERTIES
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
469 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
470 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
++, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
471 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
, MFT_STRING
, szBuffer
, MFS_DEFAULT
);
474 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, Count
);
477 HRESULT WINAPI
CCBitBucketItemContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi
)
479 SEARCH_CONTEXT Context
;
480 static LPCWSTR szDrive
= L
"C:\\";
482 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",this,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
484 if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(1) || lpcmi
->lpVerb
== MAKEINTRESOURCEA(5))
486 Context
.pFileDetails
= _ILGetRecycleStruct(apidl
);
487 Context
.bFound
= FALSE
;
489 EnumerateRecycleBinW(szDrive
, CBSearchBitBucket
, (PVOID
)&Context
);
493 if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(1))
496 if (RestoreFile(Context
.hDeletedFile
))
503 DeleteFileHandleToRecycleBin(Context
.hDeletedFile
);
507 else if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(3))
509 FIXME("implement cut\n");
512 else if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(7))
514 FIXME("implement properties\n");
521 HRESULT WINAPI
CCBitBucketItemContextMenu::GetCommandString(UINT_PTR idCommand
,UINT uFlags
, UINT
*lpReserved
, LPSTR lpszName
, UINT uMaxNameLen
)
523 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",this, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
528 HRESULT WINAPI
CCBitBucketItemContextMenu::HandleMenuMsg(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
530 TRACE("CBitBucket_IContextMenu2Item_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n",this, uMsg
, wParam
, lParam
);
535 static HRESULT WINAPI
CBitBucketItemContextMenuConstructor(REFIID riid
, LPCITEMIDLIST pidl
, LPVOID
*ppv
)
537 CComObject
<CCBitBucketItemContextMenu
> *theMenu
;
538 CComPtr
<IUnknown
> result
;
541 TRACE("%s\n", shdebugstr_guid(&riid
));
546 ATLTRY(theMenu
= new CComObject
<CCBitBucketItemContextMenu
>);
548 return E_OUTOFMEMORY
;
549 hResult
= theMenu
->QueryInterface(riid
, (void **)&result
);
555 hResult
= theMenu
->Initialize(pidl
);
558 *ppv
= result
.Detach();
559 TRACE ("--(%p)\n", *ppv
);
563 CBitBucket::CBitBucket()
568 CBitBucket::~CBitBucket()
570 /* InterlockedDecrement(&objCount);*/
574 HRESULT WINAPI
CBitBucket::ParseDisplayName(HWND hwnd
, LPBC pbc
,
575 LPOLESTR pszDisplayName
, ULONG
*pchEaten
, LPITEMIDLIST
*ppidl
,
576 ULONG
*pdwAttributes
)
583 PDELETED_FILE_DETAILS_W
584 UnpackDetailsFromPidl(LPCITEMIDLIST pidl
)
586 return (PDELETED_FILE_DETAILS_W
)&pidl
->mkid
.abID
;
589 HRESULT WINAPI
CBitBucket::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
591 CComObject
<CBitBucketEnum
> *theEnumerator
;
592 CComPtr
<IEnumIDList
> result
;
595 TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner
, dwFlags
, ppEnumIDList
);
597 if (ppEnumIDList
== NULL
)
599 *ppEnumIDList
= NULL
;
600 ATLTRY (theEnumerator
= new CComObject
<CBitBucketEnum
>);
601 if (theEnumerator
== NULL
)
602 return E_OUTOFMEMORY
;
603 hResult
= theEnumerator
->QueryInterface(IID_IEnumIDList
, (void **)&result
);
604 if (FAILED (hResult
))
606 delete theEnumerator
;
609 hResult
= theEnumerator
->Initialize(dwFlags
);
610 if (FAILED (hResult
))
612 *ppEnumIDList
= result
.Detach();
614 TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList
);
619 HRESULT WINAPI
CBitBucket::BindToObject(LPCITEMIDLIST pidl
, LPBC pbc
, REFIID riid
, void **ppv
)
621 FIXME("(%p, %p, %p, %s, %p) - stub\n", this, pidl
, pbc
, debugstr_guid(&riid
), ppv
);
625 HRESULT WINAPI
CBitBucket::BindToStorage(LPCITEMIDLIST pidl
, LPBC pbc
, REFIID riid
, void **ppv
)
627 FIXME("(%p, %p, %p, %s, %p) - stub\n", this, pidl
, pbc
, debugstr_guid(&riid
), ppv
);
631 HRESULT WINAPI
CBitBucket::CompareIDs(LPARAM lParam
, LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
634 TRACE("(%p, %p, %p, %p)\n", this, (void *)lParam
, pidl1
, pidl2
);
635 if (pidl1
->mkid
.cb
!= pidl2
->mkid
.cb
)
636 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, pidl1
->mkid
.cb
- pidl2
->mkid
.cb
);
637 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (unsigned short)memcmp(pidl1
->mkid
.abID
, pidl2
->mkid
.abID
, pidl1
->mkid
.cb
));
640 HRESULT WINAPI
CBitBucket::CreateViewObject(HWND hwndOwner
, REFIID riid
, void **ppv
)
642 LPSHELLVIEW pShellView
;
643 HRESULT hr
= E_NOINTERFACE
;
645 TRACE("(%p, %p, %s, %p)\n", this, hwndOwner
, debugstr_guid(&riid
), ppv
);
652 if (IsEqualIID (riid
, IID_IDropTarget
))
654 WARN ("IDropTarget not implemented\n");
657 else if (IsEqualIID (riid
, IID_IContextMenu
) || IsEqualIID (riid
, IID_IContextMenu2
))
659 hr
= CBitBucketBackgroundContextMenuConstructor(riid
, ppv
);
661 else if (IsEqualIID (riid
, IID_IShellView
))
663 hr
= IShellView_Constructor ((IShellFolder
*)this, &pShellView
);
666 hr
= pShellView
->QueryInterface(riid
, ppv
);
667 pShellView
->Release();
672 TRACE ("-- (%p)->(interface=%p)\n", this, ppv
);
677 HRESULT WINAPI
CBitBucket::GetAttributesOf(UINT cidl
, LPCITEMIDLIST
*apidl
,
680 TRACE("(%p, %d, {%p, ...}, {%x})\n", this, cidl
, apidl
? apidl
[0] : NULL
, (unsigned int)*rgfInOut
);
681 *rgfInOut
&= SFGAO_CANMOVE
|SFGAO_CANDELETE
|SFGAO_HASPROPSHEET
|SFGAO_FILESYSTEM
| SFGAO_FOLDER
;
685 HRESULT WINAPI
CBitBucket::GetUIObjectOf(HWND hwndOwner
, UINT cidl
, LPCITEMIDLIST
*apidl
,
686 REFIID riid
, UINT
*prgfInOut
, void **ppv
)
688 IUnknown
*pObj
= NULL
;
689 HRESULT hr
= E_INVALIDARG
;
691 TRACE ("(%p)->(%p,%u,apidl=%p, %p %p)\n", this,
692 hwndOwner
, cidl
, apidl
, prgfInOut
, ppv
);
699 if ((IsEqualIID (riid
, IID_IContextMenu
) || IsEqualIID(riid
, IID_IContextMenu2
)) && (cidl
>= 1))
701 hr
= CBitBucketItemContextMenuConstructor(riid
, apidl
[0], (void **)&pObj
);
703 else if (IsEqualIID (riid
, IID_IDropTarget
) && (cidl
>= 1))
705 hr
= this->QueryInterface(IID_IDropTarget
, (LPVOID
*) & pObj
);
710 if (SUCCEEDED(hr
) && !pObj
)
714 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
718 HRESULT WINAPI
CBitBucket::GetDisplayNameOf(LPCITEMIDLIST pidl
, SHGDNF uFlags
, STRRET
*pName
)
720 PIDLRecycleStruct
*pFileDetails
;
723 TRACE("(%p, %p, %x, %p)\n", this, pidl
, (unsigned int)uFlags
, pName
);
726 if (_ILIsBitBucket (pidl
))
730 if (HCR_GetClassNameW(CLSID_RecycleBin
, pszPath
, MAX_PATH
))
732 pName
->uType
= STRRET_WSTR
;
733 pName
->pOleStr
= StrDupW(pszPath
);
738 pFileDetails
= _ILGetRecycleStruct(pidl
);
742 pName
->uType
= STRRET_CSTR
;
746 pFileName
= wcsrchr(pFileDetails
->szName
, L
'\\');
750 pName
->uType
= STRRET_CSTR
;
754 pName
->pOleStr
= StrDupW(pFileName
+ 1);
755 if (pName
->pOleStr
== NULL
)
756 return E_OUTOFMEMORY
;
758 pName
->uType
= STRRET_WSTR
;
762 HRESULT WINAPI
CBitBucket::SetNameOf(HWND hwnd
, LPCITEMIDLIST pidl
, LPCOLESTR pszName
,
763 SHGDNF uFlags
, LPITEMIDLIST
*ppidlOut
)
766 return E_FAIL
; /* not supported */
769 HRESULT WINAPI
CBitBucket::GetDefaultSearchGUID(GUID
*pguid
)
775 HRESULT WINAPI
CBitBucket::EnumSearches(IEnumExtraSearch
**ppEnum
)
782 HRESULT WINAPI
CBitBucket::GetDefaultColumn(DWORD dwReserved
, ULONG
*pSort
, ULONG
*pDisplay
)
784 TRACE("(%p, %x, %p, %p)\n", this, (unsigned int)dwReserved
, pSort
, pDisplay
);
790 HRESULT WINAPI
CBitBucket::GetDefaultColumnState(UINT iColumn
, SHCOLSTATEF
*pcsFlags
)
792 TRACE("(%p, %d, %p)\n", this, iColumn
, pcsFlags
);
793 if (iColumn
>= COLUMNS_COUNT
)
795 *pcsFlags
= CBitBucketColumns
[iColumn
].pcsFlags
;
799 HRESULT WINAPI
CBitBucket::GetDetailsEx(LPCITEMIDLIST pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
805 static HRESULT
FormatDateTime(LPWSTR buffer
, int size
, FILETIME
* ft
)
811 FileTimeToLocalFileTime(ft
, &lft
);
812 FileTimeToSystemTime(&lft
, &time
);
814 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &time
, NULL
, buffer
, size
);
815 if (ret
>0 && ret
<size
)
817 /* Append space + time without seconds */
819 GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &time
, NULL
, &buffer
[ret
], size
- ret
);
822 return (ret
!=0 ? E_FAIL
: S_OK
);
825 HRESULT WINAPI
CBitBucket::GetDetailsOf(LPCITEMIDLIST pidl
, UINT iColumn
, LPSHELLDETAILS pDetails
)
827 PIDLRecycleStruct
* pFileDetails
;
828 WCHAR buffer
[MAX_PATH
];
829 WCHAR szTypeName
[100];
833 TRACE("(%p, %p, %d, %p)\n", this, pidl
, iColumn
, pDetails
);
834 if (iColumn
>= COLUMNS_COUNT
)
836 pDetails
->fmt
= CBitBucketColumns
[iColumn
].fmt
;
837 pDetails
->cxChar
= CBitBucketColumns
[iColumn
].cxChars
;
840 pDetails
->str
.uType
= STRRET_WSTR
;
841 LoadStringW(shell32_hInstance
, CBitBucketColumns
[iColumn
].column_name_id
, buffer
, MAX_PATH
);
842 return SHStrDupW(buffer
, &pDetails
->str
.pOleStr
);
845 if (iColumn
== COLUMN_NAME
)
846 return GetDisplayNameOf(pidl
, SHGDN_NORMAL
, &pDetails
->str
);
848 pFileDetails
= _ILGetRecycleStruct(pidl
);
852 FormatDateTime(buffer
, MAX_PATH
, &pFileDetails
->DeletionTime
);
855 pszBackslash
= wcsrchr(pFileDetails
->szName
, L
'\\');
856 Length
= (pszBackslash
- pFileDetails
->szName
);
857 memcpy((LPVOID
)buffer
, pFileDetails
->szName
, Length
* sizeof(WCHAR
));
858 buffer
[Length
] = L
'\0';
861 StrFormatKBSizeW(pFileDetails
->FileSize
.QuadPart
, buffer
, MAX_PATH
);
864 FormatDateTime(buffer
, MAX_PATH
, &pFileDetails
->LastModification
);
867 szTypeName
[0] = L
'\0';
868 wcscpy(buffer
,PathFindExtensionW(pFileDetails
->szName
));
869 if (!( HCR_MapTypeToValueW(buffer
, buffer
, sizeof(buffer
)/sizeof(WCHAR
), TRUE
) &&
870 HCR_MapTypeToValueW(buffer
, szTypeName
, sizeof(szTypeName
)/sizeof(WCHAR
), FALSE
)))
872 wcscpy (szTypeName
, PathFindExtensionW(pFileDetails
->szName
));
873 wcscat(szTypeName
, L
"-");
874 Length
= wcslen(szTypeName
);
875 if (LoadStringW(shell32_hInstance
, IDS_SHV_COLUMN1
, &szTypeName
[Length
], (sizeof(szTypeName
)/sizeof(WCHAR
))- Length
))
876 szTypeName
[(sizeof(szTypeName
)/sizeof(WCHAR
))-1] = L
'\0';
878 pDetails
->str
.uType
= STRRET_WSTR
;
879 return SHStrDupW(szTypeName
, &pDetails
->str
.pOleStr
);
885 pDetails
->str
.uType
= STRRET_WSTR
;
886 return SHStrDupW(buffer
, &pDetails
->str
.pOleStr
);
889 HRESULT WINAPI
CBitBucket::MapColumnToSCID(UINT iColumn
, SHCOLUMNID
*pscid
)
891 TRACE("(%p, %d, %p)\n", this, iColumn
, pscid
);
892 if (iColumn
>=COLUMNS_COUNT
)
894 pscid
->fmtid
= *CBitBucketColumns
[iColumn
].fmtId
;
895 pscid
->pid
= CBitBucketColumns
[iColumn
].pid
;
899 HRESULT WINAPI
CBitBucket::GetClassID(CLSID
*pClassID
)
901 TRACE("(%p, %p)\n", this, pClassID
);
902 if (pClassID
== NULL
)
904 memcpy(pClassID
, &CLSID_RecycleBin
, sizeof(CLSID
));
908 HRESULT WINAPI
CBitBucket::Initialize(LPCITEMIDLIST pidl
)
910 TRACE("(%p, %p)\n", this, pidl
);
912 SHFree((LPVOID
)this->pidl
);
913 this->pidl
= ILClone(pidl
);
914 if (this->pidl
== NULL
)
915 return E_OUTOFMEMORY
;
919 HRESULT WINAPI
CBitBucket::GetCurFolder(LPITEMIDLIST
*ppidl
)
922 *ppidl
= ILClone(pidl
);
926 /*************************************************************************
927 * BitBucket IShellExtInit interface
930 HRESULT WINAPI
CBitBucket::Initialize(LPCITEMIDLIST pidlFolder
, IDataObject
*pdtobj
, HKEY hkeyProgID
)
932 TRACE("%p %p %p %p\n", this, pidlFolder
, pdtobj
, hkeyProgID
);
936 void toggleNukeOnDeleteOption(HWND hwndDlg
, BOOL bEnable
)
940 SendDlgItemMessage(hwndDlg
, 14001, BM_SETCHECK
, BST_UNCHECKED
, 0);
941 EnableWindow(GetDlgItem(hwndDlg
, 14002), FALSE
);
942 SendDlgItemMessage(hwndDlg
, 14003, BM_SETCHECK
, BST_CHECKED
, 0);
946 SendDlgItemMessage(hwndDlg
, 14001, BM_SETCHECK
, BST_CHECKED
, 0);
947 EnableWindow(GetDlgItem(hwndDlg
, 14002), TRUE
);
948 SendDlgItemMessage(hwndDlg
, 14003, BM_SETCHECK
, BST_UNCHECKED
, 0);
954 InitializeBitBucketDlg(HWND hwndDlg
, WCHAR DefaultDrive
)
956 WCHAR CurDrive
= L
'A';
957 WCHAR szDrive
[] = L
"A:\\";
961 DWORD MaxComponent
, Flags
;
967 ULARGE_INTEGER TotalNumberOfFreeBytes
, TotalNumberOfBytes
, FreeBytesAvailable
;
972 PDRIVE_ITEM_CONTEXT pItem
= NULL
, pDefault
= NULL
, pFirst
= NULL
;
974 hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
976 if (!LoadStringW(shell32_hInstance
, IDS_RECYCLEBIN_LOCATION
, szVolume
, sizeof(szVolume
) / sizeof(WCHAR
)))
979 GetClientRect(hDlgCtrl
, &rect
);
981 memset(&lc
, 0, sizeof(LV_COLUMN
) );
982 lc
.mask
= LVCF_WIDTH
| LVCF_TEXT
| LVCF_SUBITEM
| LVCF_FMT
;
984 columnSize
= 140; //FIXME
986 lc
.fmt
= LVCFMT_FIXED_WIDTH
;
988 lc
.cchTextMax
= wcslen(szVolume
);
989 lc
.pszText
= szVolume
;
990 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&lc
);
992 if (!LoadStringW(shell32_hInstance
, IDS_RECYCLEBIN_DISKSPACE
, szVolume
, sizeof(szVolume
) / sizeof(WCHAR
)))
996 lc
.cx
= rect
.right
- rect
.left
- columnSize
;
997 lc
.cchTextMax
= wcslen(szVolume
);
998 lc
.pszText
= szVolume
;
999 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&lc
);
1001 dwDrives
= GetLogicalDrives();
1005 if ((dwDrives
& 0x1))
1007 UINT Type
= GetDriveTypeW(szDrive
);
1008 if (Type
== DRIVE_FIXED
) //FIXME
1010 if (!GetVolumeInformationW(szDrive
, szName
, sizeof(szName
) / sizeof(WCHAR
), &dwSerial
, &MaxComponent
, &Flags
, NULL
, 0))
1016 swprintf(szVolume
, L
"%s (%c)", szName
, szDrive
[0]);
1017 memset(&li
, 0x0, sizeof(LVITEMW
));
1018 li
.mask
= LVIF_TEXT
| LVIF_PARAM
;
1020 li
.pszText
= szVolume
;
1021 li
.iItem
= itemCount
;
1022 (void)SendMessageW(hDlgCtrl
, LVM_INSERTITEMW
, 0, (LPARAM
)&li
);
1023 if (GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailable
, &TotalNumberOfBytes
, &TotalNumberOfFreeBytes
))
1025 if (StrFormatByteSizeW(TotalNumberOfFreeBytes
.QuadPart
, szVolume
, sizeof(szVolume
) / sizeof(WCHAR
)))
1028 pItem
= (DRIVE_ITEM_CONTEXT
*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DRIVE_ITEM_CONTEXT
));
1031 swprintf(szName
, L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\%04X-%04X", LOWORD(dwSerial
), HIWORD(dwSerial
));
1032 dwSize
= sizeof(DWORD
);
1033 RegGetValueW(HKEY_CURRENT_USER
, szName
, L
"MaxCapacity", RRF_RT_DWORD
, NULL
, &pItem
->dwMaxCapacity
, &dwSize
);
1034 dwSize
= sizeof(DWORD
);
1035 RegGetValueW(HKEY_CURRENT_USER
, szName
, L
"NukeOnDelete", RRF_RT_DWORD
, NULL
, &pItem
->dwNukeOnDelete
, &dwSize
);
1036 pItem
->dwSerial
= dwSerial
;
1037 li
.mask
= LVIF_PARAM
;
1038 li
.lParam
= (LPARAM
)pItem
;
1039 (void)SendMessageW(hDlgCtrl
, LVM_SETITEMW
, 0, (LPARAM
)&li
);
1040 if (CurDrive
== DefaultDrive
)
1042 defIndex
= itemCount
;
1049 li
.mask
= LVIF_TEXT
;
1051 li
.pszText
= szVolume
;
1052 li
.iItem
= itemCount
;
1053 (void)SendMessageW(hDlgCtrl
, LVM_SETITEMW
, 0, (LPARAM
)&li
);
1060 szDrive
[0] = CurDrive
;
1061 dwDrives
= (dwDrives
>> 1);
1068 toggleNukeOnDeleteOption(hwndDlg
, pDefault
->dwNukeOnDelete
);
1069 SetDlgItemInt(hwndDlg
, 14002, pDefault
->dwMaxCapacity
, FALSE
);
1071 ZeroMemory(&li
, sizeof(li
));
1072 li
.mask
= LVIF_STATE
;
1073 li
.stateMask
= (UINT
)-1;
1074 li
.state
= LVIS_FOCUSED
|LVIS_SELECTED
;
1075 li
.iItem
= defIndex
;
1076 (void)SendMessageW(hDlgCtrl
, LVM_SETITEMW
, 0, (LPARAM
)&li
);
1080 static BOOL
StoreDriveSettings(HWND hwndDlg
)
1083 HWND hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
1085 PDRIVE_ITEM_CONTEXT pItem
;
1091 if (RegCreateKeyExW(HKEY_CURRENT_USER
, L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume", 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
1094 iCount
= ListView_GetItemCount(hDlgCtrl
);
1096 ZeroMemory(&li
, sizeof(li
));
1097 li
.mask
= LVIF_PARAM
;
1099 for(iIndex
= 0; iIndex
< iCount
; iIndex
++)
1102 if (SendMessageW(hDlgCtrl
, LVM_GETITEMW
, 0, (LPARAM
)&li
))
1104 pItem
= (PDRIVE_ITEM_CONTEXT
)li
.lParam
;
1105 swprintf(szSerial
, L
"%04X-%04X", LOWORD(pItem
->dwSerial
), HIWORD(pItem
->dwSerial
));
1106 if (RegCreateKeyExW(hKey
, szSerial
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hSubKey
, NULL
) == ERROR_SUCCESS
)
1108 dwSize
= sizeof(DWORD
);
1109 RegSetValueExW(hSubKey
, L
"NukeOnDelete", 0, REG_DWORD
, (LPBYTE
)&pItem
->dwNukeOnDelete
, dwSize
);
1110 dwSize
= sizeof(DWORD
);
1111 RegSetValueExW(hSubKey
, L
"MaxCapacity", 0, REG_DWORD
, (LPBYTE
)&pItem
->dwMaxCapacity
, dwSize
);
1112 RegCloseKey(hSubKey
);
1121 static VOID
FreeDriveItemContext(HWND hwndDlg
)
1124 HWND hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
1127 iCount
= ListView_GetItemCount(hDlgCtrl
);
1129 ZeroMemory(&li
, sizeof(li
));
1130 li
.mask
= LVIF_PARAM
;
1132 for(iIndex
= 0; iIndex
< iCount
; iIndex
++)
1135 if (SendMessageW(hDlgCtrl
, LVM_GETITEMW
, 0, (LPARAM
)&li
))
1137 HeapFree(GetProcessHeap(), 0, (LPVOID
)li
.lParam
);
1143 GetDefaultItem(HWND hwndDlg
, LVITEMW
* li
)
1146 UINT iItemCount
, iIndex
;
1148 hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
1152 iItemCount
= ListView_GetItemCount(hDlgCtrl
);
1156 ZeroMemory(li
, sizeof(LVITEMW
));
1157 li
->mask
= LVIF_PARAM
| LVIF_STATE
;
1158 li
->stateMask
= (UINT
)-1;
1159 for (iIndex
= 0; iIndex
< iItemCount
; iIndex
++)
1162 if (SendMessageW(hDlgCtrl
, LVM_GETITEMW
, 0, (LPARAM
)li
))
1164 if (li
->state
& LVIS_SELECTED
)
1184 PDRIVE_ITEM_CONTEXT pItem
;
1187 PROPSHEETPAGE
* page
;
1193 page
= (PROPSHEETPAGE
*)lParam
;
1194 InitializeBitBucketDlg(hwndDlg
, (WCHAR
)page
->lParam
);
1195 dwStyle
= (DWORD
) SendDlgItemMessage(hwndDlg
, 14000, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
1196 dwStyle
= dwStyle
| LVS_EX_FULLROWSELECT
;
1197 SendDlgItemMessage(hwndDlg
, 14000, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, dwStyle
);
1198 if (GetDlgCtrlID((HWND
)wParam
) != 14000)
1200 SetFocus(GetDlgItem(hwndDlg
, 14000));
1205 switch(LOWORD(wParam
))
1208 toggleNukeOnDeleteOption(hwndDlg
, FALSE
);
1209 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1212 toggleNukeOnDeleteOption(hwndDlg
, TRUE
);
1213 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1216 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1221 lppsn
= (LPPSHNOTIFY
) lParam
;
1222 lppl
= (LPNMLISTVIEW
) lParam
;
1223 if (lppsn
->hdr
.code
== PSN_APPLY
)
1225 if (GetDefaultItem(hwndDlg
, &li
) > -1)
1227 pItem
= (PDRIVE_ITEM_CONTEXT
)li
.lParam
;
1230 uResult
= GetDlgItemInt(hwndDlg
, 14002, &bSuccess
, FALSE
);
1232 pItem
->dwMaxCapacity
= uResult
;
1233 if (SendDlgItemMessageW(hwndDlg
, 14003, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
1234 pItem
->dwNukeOnDelete
= TRUE
;
1236 pItem
->dwNukeOnDelete
= FALSE
;
1239 if (StoreDriveSettings(hwndDlg
))
1241 SetWindowLongPtr( hwndDlg
, DWL_MSGRESULT
, PSNRET_NOERROR
);
1245 else if (lppl
->hdr
.code
== LVN_ITEMCHANGING
)
1247 ZeroMemory(&li
, sizeof(li
));
1248 li
.mask
= LVIF_PARAM
;
1249 li
.iItem
= lppl
->iItem
;
1250 if (!SendMessageW(lppl
->hdr
.hwndFrom
, LVM_GETITEMW
, 0, (LPARAM
)&li
))
1253 pItem
= (PDRIVE_ITEM_CONTEXT
)li
.lParam
;
1257 if (!(lppl
->uOldState
& LVIS_FOCUSED
) && (lppl
->uNewState
& LVIS_FOCUSED
))
1259 /* new focused item */
1260 toggleNukeOnDeleteOption(lppl
->hdr
.hwndFrom
, pItem
->dwNukeOnDelete
);
1261 SetDlgItemInt(hwndDlg
, 14002, pItem
->dwMaxCapacity
, FALSE
);
1263 else if ((lppl
->uOldState
& LVIS_FOCUSED
) && !(lppl
->uNewState
& LVIS_FOCUSED
))
1266 uResult
= GetDlgItemInt(hwndDlg
, 14002, &bSuccess
, FALSE
);
1268 pItem
->dwMaxCapacity
= uResult
;
1269 if (SendDlgItemMessageW(hwndDlg
, 14003, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
1270 pItem
->dwNukeOnDelete
= TRUE
;
1272 pItem
->dwNukeOnDelete
= FALSE
;
1279 FreeDriveItemContext(hwndDlg
);
1285 BOOL
SH_ShowRecycleBinProperties(WCHAR sDrive
)
1287 HPROPSHEETPAGE hpsp
[1];
1288 PROPSHEETHEADERW psh
;
1289 HPROPSHEETPAGE hprop
;
1294 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
1295 psh
.dwSize
= sizeof(PROPSHEETHEADERW
);
1296 psh
.dwFlags
= PSP_DEFAULT
| PSH_PROPTITLE
;
1297 psh
.pszCaption
= MAKEINTRESOURCEW(IDS_RECYCLEBIN_FOLDER_NAME
);
1298 psh
.hwndParent
= NULL
;
1300 psh
.hInstance
= shell32_hInstance
;
1302 hprop
= SH_CreatePropertySheetPage("BITBUCKET_PROPERTIES_DLG", BitBucketDlg
, (LPARAM
)sDrive
, NULL
);
1305 ERR("Failed to create property sheet\n");
1308 hpsp
[psh
.nPages
] = hprop
;
1312 ret
= PropertySheetW(&psh
);
1320 TRASH_CanTrashFile(LPCWSTR wszPath
)
1323 DWORD dwNukeOnDelete
, dwType
, VolSerialNumber
, MaxComponentLength
;
1324 DWORD FileSystemFlags
, dwSize
, dwDisposition
;
1327 WCHAR szKey
[150] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\";
1329 if (wszPath
[1] != L
':')
1335 if (GetDriveTypeW(wszPath
) != DRIVE_FIXED
)
1337 /* no bitbucket on removable media */
1341 if (!GetVolumeInformationW(wszPath
, NULL
, 0, &VolSerialNumber
, &MaxComponentLength
, &FileSystemFlags
, NULL
, 0))
1343 ERR("GetVolumeInformationW failed with %u\n", GetLastError());
1347 swprintf(szBuffer
, L
"%04X-%04X", LOWORD(VolSerialNumber
), HIWORD(VolSerialNumber
));
1348 wcscat(szKey
, szBuffer
);
1350 if (RegCreateKeyExW(HKEY_CURRENT_USER
, szKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, &dwDisposition
) != ERROR_SUCCESS
)
1352 ERR("RegCreateKeyExW failed\n");
1356 if (dwDisposition
& REG_CREATED_NEW_KEY
)
1358 /* per default move to bitbucket */
1360 RegSetValueExW(hKey
, L
"NukeOnDelete", 0, REG_DWORD
, (LPBYTE
)&dwNukeOnDelete
, sizeof(DWORD
));
1361 /* per default unlimited size */
1363 RegSetValueExW(hKey
, L
"MaxCapacity", 0, REG_DWORD
, (LPBYTE
)&dwSize
, sizeof(DWORD
));
1369 dwSize
= sizeof(dwNukeOnDelete
);
1370 ret
= RegQueryValueExW(hKey
, L
"NukeOnDelete", NULL
, &dwType
, (LPBYTE
)&dwNukeOnDelete
, &dwSize
);
1371 if (ret
!= ERROR_SUCCESS
)
1373 if (ret
== ERROR_FILE_NOT_FOUND
)
1375 /* restore key and enable bitbucket */
1377 RegSetValueExW(hKey
, L
"NukeOnDelete", 0, REG_DWORD
, (LPBYTE
)&dwNukeOnDelete
, sizeof(DWORD
));
1382 else if (dwNukeOnDelete
)
1384 /* do not delete to bitbucket */
1389 * check if bitbucket is full
1397 TRASH_TrashFile(LPCWSTR wszPath
)
1399 TRACE("(%s)\n", debugstr_w(wszPath
));
1400 return DeleteFileToRecycleBin(wszPath
);
1403 /*************************************************************************
1404 * SHUpdateCBitBucketIcon [SHELL32.@]
1408 EXTERN_C HRESULT WINAPI
SHUpdateRecycleBinIcon(void)