Author: hpoussin Date: Tue Nov 27 11:22:16 2007 New Revision: 30811
URL: http://svn.reactos.org/svn/reactos?rev=30811&view=rev Log: Better compatibility with MS Windows recycle bin Add traces
Modified: trunk/reactos/lib/recyclebin/readme.txt trunk/reactos/lib/recyclebin/recyclebin.c trunk/reactos/lib/recyclebin/recyclebin_generic.c trunk/reactos/lib/recyclebin/recyclebin_generic_enumerator.c trunk/reactos/lib/recyclebin/recyclebin_private.h trunk/reactos/lib/recyclebin/recyclebin_v5.c trunk/reactos/lib/recyclebin/recyclebin_v5.h trunk/reactos/lib/recyclebin/recyclebin_v5_enumerator.c
Modified: trunk/reactos/lib/recyclebin/readme.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/recyclebin/readme.txt?r... ============================================================================== --- trunk/reactos/lib/recyclebin/readme.txt (original) +++ trunk/reactos/lib/recyclebin/readme.txt Tue Nov 27 11:22:16 2007 @@ -4,7 +4,6 @@ TODO - Empty a recycle bin containing directories (v5) - Set security on recycle bin folder -- Delete files > 4Gb - Make the library thread-safe
3 levels
Modified: trunk/reactos/lib/recyclebin/recyclebin.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/recyclebin/recyclebin.c... ============================================================================== --- trunk/reactos/lib/recyclebin/recyclebin.c (original) +++ trunk/reactos/lib/recyclebin/recyclebin.c Tue Nov 27 11:22:16 2007 @@ -10,12 +10,16 @@ #include "recyclebin_private.h" #include <stdio.h>
+WINE_DEFAULT_DEBUG_CHANNEL(recyclebin); + BOOL WINAPI CloseRecycleBinHandle( IN HANDLE hDeletedFile) { IRecycleBinFile *rbf = (IRecycleBinFile *)hDeletedFile; HRESULT hr; + + TRACE("(%p)\n", hDeletedFile);
hr = IRecycleBinFile_Release(rbf); if (SUCCEEDED(hr)) @@ -35,6 +39,8 @@ LPWSTR FileNameW = NULL; BOOL ret = FALSE;
+ TRACE("(%s)\n", debugstr_a(FileName)); + /* Check parameters */ if (FileName == NULL) { @@ -67,6 +73,8 @@ { IRecycleBin *prb; HRESULT hr; + + TRACE("(%s)\n", debugstr_w(FileName));
hr = GetDefaultRecycleBin(NULL, &prb); if (!SUCCEEDED(hr)) @@ -93,6 +101,8 @@ LPWSTR szRootW = NULL; BOOL ret = FALSE;
+ TRACE("(%s)\n", debugstr_a(pszRoot)); + if (pszRoot) { len = MultiByteToWideChar(CP_ACP, 0, pszRoot, -1, NULL, 0); @@ -121,6 +131,8 @@ { IRecycleBin *prb; HRESULT hr; + + TRACE("(%s)\n", debugstr_w(pszRoot));
hr = GetDefaultRecycleBin(pszRoot, &prb); if (!SUCCEEDED(hr)) @@ -149,6 +161,8 @@ LPWSTR szRootW = NULL; BOOL ret = FALSE;
+ TRACE("(%s, %p, %p)\n", debugstr_a(pszRoot), pFnCallback, Context); + if (pszRoot) { len = MultiByteToWideChar(CP_ACP, 0, pszRoot, -1, NULL, 0); @@ -181,6 +195,8 @@ IRecycleBinEnumList *prbel = NULL; IRecycleBinFile *prbf; HRESULT hr; + + TRACE("(%s, %p, %p)\n", debugstr_w(pszRoot), pFnCallback, Context);
hr = GetDefaultRecycleBin(NULL, &prb); if (!SUCCEEDED(hr)) @@ -231,6 +247,8 @@ DWORD BufferSizeW = 0; BOOL ret = FALSE;
+ TRACE("(%p, %lu, %p, %p)\n", hDeletedFile, BufferSize, FileDetails, RequiredSize); + if (BufferSize >= FIELD_OFFSET(DELETED_FILE_DETAILS_A, FileName)) { BufferSizeW = FIELD_OFFSET(DELETED_FILE_DETAILS_W, FileName) @@ -274,6 +292,8 @@ HRESULT hr; SIZE_T NameSize, Needed;
+ TRACE("(%p, %lu, %p, %p)\n", hDeletedFile, BufferSize, FileDetails, RequiredSize); + hr = IRecycleBinFile_GetFileName(rbf, 0, NULL, &NameSize); if (!SUCCEEDED(hr)) goto cleanup; @@ -321,6 +341,8 @@ IRecycleBinFile *rbf = (IRecycleBinFile *)hDeletedFile; HRESULT hr;
+ TRACE("(%p)\n", hDeletedFile); + hr = IRecycleBinFile_Restore(rbf); if (SUCCEEDED(hr)) return TRUE; @@ -339,6 +361,8 @@ IUnknown *pUnk; HRESULT hr;
+ TRACE("(%s, %p)\n", debugstr_w(pszVolume), pprb); + if (!pprb) return E_POINTER;
Modified: trunk/reactos/lib/recyclebin/recyclebin_generic.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/recyclebin/recyclebin_g... ============================================================================== --- trunk/reactos/lib/recyclebin/recyclebin_generic.c (original) +++ trunk/reactos/lib/recyclebin/recyclebin_generic.c Tue Nov 27 11:22:16 2007 @@ -19,7 +19,7 @@ };
static HRESULT STDMETHODCALLTYPE -RecycleBinGenericVtbl_RecycleBin_QueryInterface( +RecycleBinGeneric_RecycleBin_QueryInterface( IRecycleBin *This, REFIID riid, void **ppvObject) @@ -46,7 +46,7 @@ }
static ULONG STDMETHODCALLTYPE -RecycleBinGenericVtbl_RecycleBin_AddRef( +RecycleBinGeneric_RecycleBin_AddRef( IRecycleBin *This) { struct RecycleBinGeneric *s = CONTAINING_RECORD(This, struct RecycleBinGeneric, recycleBinImpl); @@ -55,8 +55,17 @@ return refCount; }
+static VOID +RecycleBinGeneric_Destructor( + struct RecycleBinGeneric *s) +{ + TRACE("(%p)\n", s); + + CoTaskMemFree(s); +} + static ULONG STDMETHODCALLTYPE -RecycleBinGenericVtbl_RecycleBin_Release( +RecycleBinGeneric_RecycleBin_Release( IRecycleBin *This) { struct RecycleBinGeneric *s = CONTAINING_RECORD(This, struct RecycleBinGeneric, recycleBinImpl); @@ -67,13 +76,13 @@ refCount = InterlockedDecrement((PLONG)&s->ref);
if (refCount == 0) - CoTaskMemFree(s); + RecycleBinGeneric_Destructor(s);
return refCount; }
static HRESULT STDMETHODCALLTYPE -RecycleBinGenericVtbl_RecycleBin_DeleteFile( +RecycleBinGeneric_RecycleBin_DeleteFile( IN IRecycleBin *This, IN LPCWSTR szFileName) { @@ -140,7 +149,7 @@ }
static HRESULT STDMETHODCALLTYPE -RecycleBinGenericVtbl_RecycleBin_EmptyRecycleBin( +RecycleBinGeneric_RecycleBin_EmptyRecycleBin( IN IRecycleBin *This) { WCHAR szVolumeName[MAX_PATH]; @@ -161,7 +170,7 @@ swprintf(szVolumeName, L"%c:\", 'A' + i); if (GetDriveTypeW(szVolumeName) != DRIVE_FIXED) continue; - + hr = GetDefaultRecycleBin(szVolumeName, &prb); if (!SUCCEEDED(hr)) return hr; @@ -174,22 +183,22 @@ }
static HRESULT STDMETHODCALLTYPE -RecycleBinGenericVtbl_RecycleBin_EnumObjects( +RecycleBinGeneric_RecycleBin_EnumObjects( IN IRecycleBin *This, OUT IRecycleBinEnumList **ppEnumList) { TRACE("(%p, %p)\n", This, ppEnumList); - return RecycleBinGeneric_Enumerator_Constructor(ppEnumList); + return RecycleBinGenericEnum_Constructor(ppEnumList); }
CONST_VTBL struct IRecycleBinVtbl RecycleBinGenericVtbl = { - RecycleBinGenericVtbl_RecycleBin_QueryInterface, - RecycleBinGenericVtbl_RecycleBin_AddRef, - RecycleBinGenericVtbl_RecycleBin_Release, - RecycleBinGenericVtbl_RecycleBin_DeleteFile, - RecycleBinGenericVtbl_RecycleBin_EmptyRecycleBin, - RecycleBinGenericVtbl_RecycleBin_EnumObjects, + RecycleBinGeneric_RecycleBin_QueryInterface, + RecycleBinGeneric_RecycleBin_AddRef, + RecycleBinGeneric_RecycleBin_Release, + RecycleBinGeneric_RecycleBin_DeleteFile, + RecycleBinGeneric_RecycleBin_EmptyRecycleBin, + RecycleBinGeneric_RecycleBin_EnumObjects, };
HRESULT RecycleBinGeneric_Constructor(OUT IUnknown **ppUnknown)
Modified: trunk/reactos/lib/recyclebin/recyclebin_generic_enumerator.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/recyclebin/recyclebin_g... ============================================================================== --- trunk/reactos/lib/recyclebin/recyclebin_generic_enumerator.c (original) +++ trunk/reactos/lib/recyclebin/recyclebin_generic_enumerator.c Tue Nov 27 11:22:16 2007 @@ -58,6 +58,17 @@ return refCount; }
+static VOID +RecycleBinGenericEnum_Destructor( + struct RecycleBinGenericEnum *s) +{ + TRACE("(%p)\n", s); + + if (s->current) + IRecycleBinEnumList_Release(s->current); + CoTaskMemFree(s); +} + static ULONG STDMETHODCALLTYPE RecycleBinGenericEnum_RecycleBinEnumList_Release( IN IRecycleBinEnumList *This) @@ -70,11 +81,7 @@ refCount = InterlockedDecrement((PLONG)&s->ref);
if (refCount == 0) - { - if (s->current) - IRecycleBinEnumList_Release(s->current); - CoTaskMemFree(s); - } + RecycleBinGenericEnum_Destructor(s);
return refCount; } @@ -213,7 +220,7 @@ };
HRESULT -RecycleBinGeneric_Enumerator_Constructor( +RecycleBinGenericEnum_Constructor( OUT IRecycleBinEnumList **pprbel) { struct RecycleBinGenericEnum *s;
Modified: trunk/reactos/lib/recyclebin/recyclebin_private.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/recyclebin/recyclebin_p... ============================================================================== --- trunk/reactos/lib/recyclebin/recyclebin_private.h (original) +++ trunk/reactos/lib/recyclebin/recyclebin_private.h Tue Nov 27 11:22:16 2007 @@ -3,21 +3,12 @@ #include <wine/debug.h>
/* Defines */ -#define RECYCLEBIN_MAGIC 0x6e694252 -#define DELETEDFILE_MAGIC 0x6e694253
#define RECYCLE_BIN_DIRECTORY_WITH_ACL L"RECYCLER" #define RECYCLE_BIN_DIRECTORY_WITHOUT_ACL L"RECYCLED" #define RECYCLE_BIN_FILE_NAME L"INFO2"
#define ROUND_UP(N, S) ((( (N) + (S) - 1) / (S) ) * (S) ) - -/* List manipulation */ -#define InitializeListHead(le) (void)((le)->Flink = (le)->Blink = (le)) -#define InsertTailList(le,e) do { PLIST_ENTRY b = (le)->Blink; (e)->Flink = (le); (e)->Blink = b; b->Flink = (e); (le)->Blink = (e); } while (0) -#define RemoveEntryList(Entry) { PLIST_ENTRY _EX_Blink, _EX_Flink; _EX_Flink = (Entry)->Flink; _EX_Blink = (Entry)->Blink; _EX_Blink->Flink = _EX_Flink; _EX_Flink->Blink = _EX_Blink; } - -/* Typedefs */
/* Structures on disk */
@@ -26,8 +17,8 @@ typedef struct _INFO2_HEADER { DWORD dwVersion; - DWORD dwNumberOfEntries; - DWORD dwHighestRecordUniqueId; + DWORD dwNumberOfEntries; /* unused */ + DWORD dwHighestRecordUniqueId; /* unused */ DWORD dwRecordSize; DWORD dwTotalLogicalSize; } INFO2_HEADER, *PINFO2_HEADER; @@ -42,7 +33,7 @@
/* recyclebin_generic_enumerator.c */
-HRESULT RecycleBinGeneric_Enumerator_Constructor(OUT IRecycleBinEnumList **pprbel); +HRESULT RecycleBinGenericEnum_Constructor(OUT IRecycleBinEnumList **pprbel);
/* recyclebin_v5.c */
Modified: trunk/reactos/lib/recyclebin/recyclebin_v5.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/recyclebin/recyclebin_v... ============================================================================== --- trunk/reactos/lib/recyclebin/recyclebin_v5.c (original) +++ trunk/reactos/lib/recyclebin/recyclebin_v5.c Tue Nov 27 11:22:16 2007 @@ -67,7 +67,7 @@ };
static HRESULT STDMETHODCALLTYPE -RecycleBin5_RecycleBin5_QueryInterface( +RecycleBin5_RecycleBin5_QueryInterface( IRecycleBin5 *This, REFIID riid, void **ppvObject) @@ -105,6 +105,19 @@ return refCount; }
+static VOID +RecycleBin5_Destructor( + struct RecycleBin5 *s) +{ + TRACE("(%p)\n", s); + + if (s->hInfo && s->hInfo != INVALID_HANDLE_VALUE) + CloseHandle(s->hInfo); + if (s->hInfoMapped) + CloseHandle(s->hInfoMapped); + CoTaskMemFree(s); +} + static ULONG STDMETHODCALLTYPE RecycleBin5_RecycleBin5_Release( IRecycleBin5 *This) @@ -117,11 +130,7 @@ refCount = InterlockedDecrement((PLONG)&s->ref);
if (refCount == 0) - { - CloseHandle(s->hInfo); - CloseHandle(s->hInfoMapped); - CoTaskMemFree(s); - } + RecycleBin5_Destructor(s);
return refCount; } @@ -141,8 +150,8 @@ HANDLE hFile = INVALID_HANDLE_VALUE; PINFO2_HEADER pHeader = NULL; PDELETED_FILE_RECORD pDeletedFile; - ULARGE_INTEGER fileSize; - DWORD dwAttributes; + ULARGE_INTEGER FileSize; + DWORD dwAttributes, dwEntries; SYSTEMTIME SystemTime; DWORD ClusterSize, BytesPerSector, SectorsPerCluster; HRESULT hr; @@ -209,37 +218,51 @@ hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; } - pDeletedFile = ((PDELETED_FILE_RECORD)(pHeader + 1)) + pHeader->dwNumberOfEntries; + + /* Get number of entries */ + FileSize.u.LowPart = GetFileSize(s->hInfo, &FileSize.u.HighPart); + if (FileSize.u.LowPart < sizeof(INFO2_HEADER)) + { + UnmapViewOfFile(pHeader); + return HRESULT_FROM_WIN32(GetLastError()); + } + dwEntries = (DWORD)((FileSize.QuadPart - sizeof(INFO2_HEADER)) / sizeof(DELETED_FILE_RECORD)) - 1; + pDeletedFile = ((PDELETED_FILE_RECORD)(pHeader + 1)) + dwEntries;
/* Get file size */ #if 0 - if (!GetFileSizeEx(hFile, (PLARGE_INTEGER)&fileSize)) + if (!GetFileSizeEx(hFile, (PLARGE_INTEGER)&FileSize)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; } #else - fileSize.u.LowPart = GetFileSize(hFile, &fileSize.u.HighPart); - if (fileSize.u.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) + FileSize.u.LowPart = GetFileSize(hFile, &FileSize.u.HighPart); + if (FileSize.u.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) { hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; } #endif /* Check if file size is > 4Gb */ - if (fileSize.u.HighPart != 0) - { - /* FIXME: how to delete files >= 4Gb? */ - hr = E_NOTIMPL; - goto cleanup; - } - pHeader->dwTotalLogicalSize += fileSize.u.LowPart; + if (FileSize.u.HighPart != 0) + { + /* Yes, this recyclebin can't support this file */ + hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + goto cleanup; + } + pHeader->dwTotalLogicalSize += FileSize.u.LowPart;
/* Generate new name */ - pHeader->dwHighestRecordUniqueId++; Extension = wcsrchr(szFullName, '.'); ZeroMemory(pDeletedFile, sizeof(DELETED_FILE_RECORD)); - pDeletedFile->dwRecordUniqueId = pHeader->dwHighestRecordUniqueId; + if (dwEntries == 0) + pDeletedFile->dwRecordUniqueId = 0; + else + { + PDELETED_FILE_RECORD pLastDeleted = ((PDELETED_FILE_RECORD)(pHeader + 1)) + dwEntries - 1; + pDeletedFile->dwRecordUniqueId = pLastDeleted->dwRecordUniqueId + 1; + } pDeletedFile->dwDriveNumber = tolower(szFullName[0]) - 'a'; _snwprintf(DeletedFileName, MAX_PATH, L"%s\D%c%lu%s", s->Folder, pDeletedFile->dwDriveNumber + 'a', pDeletedFile->dwRecordUniqueId, Extension);
@@ -258,7 +281,7 @@ hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; } - pDeletedFile->dwPhysicalFileSize = ROUND_UP(fileSize.u.LowPart, ClusterSize); + pDeletedFile->dwPhysicalFileSize = ROUND_UP(FileSize.u.LowPart, ClusterSize);
/* Set name */ wcscpy(pDeletedFile->FileNameW, szFullName); @@ -268,7 +291,6 @@ SetLastError(ERROR_INVALID_NAME); goto cleanup; } - pHeader->dwNumberOfEntries++;
/* Move file */ if (MoveFileW(szFullName, DeletedFileName)) @@ -323,7 +345,7 @@
TRACE("(%p, %p)\n", This, ppEnumList);
- hr = RecycleBin5_Enumerator_Constructor(This, s->hInfo, s->hInfoMapped, s->Folder, &pUnk); + hr = RecycleBin5Enum_Constructor(This, s->hInfo, s->hInfoMapped, s->Folder, &pUnk); if (!SUCCEEDED(hr)) return hr;
@@ -353,7 +375,7 @@
if (s->EnumeratorCount != 0) return E_FAIL; - + pHeader = MapViewOfFile(s->hInfoMapped, FILE_MAP_WRITE, 0, 0, 0); if (!pHeader) return HRESULT_FROM_WIN32(GetLastError()); @@ -729,13 +751,7 @@ if (!SUCCEEDED(hr)) { if (s) - { - if (s->hInfo && s->hInfo != INVALID_HANDLE_VALUE) - CloseHandle(s->hInfo); - if (s->hInfoMapped) - CloseHandle(s->hInfoMapped); - CoTaskMemFree(s); - } + RecycleBin5_Destructor(s); } return hr; }
Modified: trunk/reactos/lib/recyclebin/recyclebin_v5.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/recyclebin/recyclebin_v... ============================================================================== --- trunk/reactos/lib/recyclebin/recyclebin_v5.h (original) +++ trunk/reactos/lib/recyclebin/recyclebin_v5.h Tue Nov 27 11:22:16 2007 @@ -97,7 +97,7 @@ #endif
HRESULT -RecycleBin5_Enumerator_Constructor( +RecycleBin5Enum_Constructor( IN IRecycleBin5 *prb, IN HANDLE hInfo, IN HANDLE hInfoMapped,
Modified: trunk/reactos/lib/recyclebin/recyclebin_v5_enumerator.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/recyclebin/recyclebin_v... ============================================================================== --- trunk/reactos/lib/recyclebin/recyclebin_v5_enumerator.c (original) +++ trunk/reactos/lib/recyclebin/recyclebin_v5_enumerator.c Tue Nov 27 11:22:16 2007 @@ -57,6 +57,16 @@ return refCount; }
+static VOID +RecycleBin5File_Destructor( + struct RecycleBin5File *s) +{ + TRACE("(%p)\n", s); + + IRecycleBin5_Release(s->recycleBin); + CoTaskMemFree(s); +} + static ULONG STDMETHODCALLTYPE RecycleBin5File_RecycleBinFile_Release( IN IRecycleBinFile *This) @@ -69,10 +79,7 @@ refCount = InterlockedDecrement((PLONG)&s->ref);
if (refCount == 0) - { - IRecycleBin5_Release(s->recycleBin); - CoTaskMemFree(s); - } + RecycleBin5File_Destructor(s);
return refCount; } @@ -240,7 +247,7 @@ };
static HRESULT -RecycleBin5_File_Constructor( +RecycleBin5File_Constructor( IN IRecycleBin5 *prb, IN LPCWSTR Folder, IN PDELETED_FILE_RECORD pDeletedFile, @@ -272,6 +279,11 @@ IRecycleBin5_AddRef(s->recycleBin); *ppFile = &s->recycleBinFileImpl; wsprintfW(s->FullName, L"%s\D%c%lu%s", Folder, pDeletedFile->dwDriveNumber + 'a', pDeletedFile->dwRecordUniqueId, Extension); + if (GetFileAttributesW(s->FullName) == INVALID_FILE_ATTRIBUTES) + { + RecycleBin5File_Destructor(s); + return E_FAIL; + }
return S_OK; } @@ -324,6 +336,18 @@ return refCount; }
+static VOID +RecycleBin5Enum_Destructor( + struct RecycleBin5Enum *s) +{ + TRACE("(%p)\n", s); + + IRecycleBin5_OnClosing(s->recycleBin, &s->recycleBinEnumImpl); + UnmapViewOfFile(s->pInfo); + IRecycleBin5_Release(s->recycleBin); + CoTaskMemFree(s); +} + static ULONG STDMETHODCALLTYPE RecycleBin5Enum_RecycleBinEnumList_Release( IN IRecycleBinEnumList *This) @@ -336,12 +360,7 @@ refCount = InterlockedDecrement((PLONG)&s->ref);
if (refCount == 0) - { - IRecycleBin5_OnClosing(s->recycleBin, This); - UnmapViewOfFile(s->pInfo); - IRecycleBin5_Release(s->recycleBin); - CoTaskMemFree(s); - } + RecycleBin5Enum_Destructor(s);
return refCount; } @@ -377,15 +396,10 @@ pDeletedFile = (DELETED_FILE_RECORD *)(pHeader + 1) + i; for (; i < dwEntries && fetched < celt; i++) { - hr = RecycleBin5_File_Constructor(s->recycleBin, s->szPrefix, pDeletedFile, &rgelt[fetched]); - if (!SUCCEEDED(hr)) - { - for (i = 0; i < fetched; i++) - IRecycleBinFile_Release(rgelt[i]); - return hr; - } + hr = RecycleBin5File_Constructor(s->recycleBin, s->szPrefix, pDeletedFile, &rgelt[fetched]); + if (SUCCEEDED(hr)) + fetched++; pDeletedFile++; - fetched++; }
s->dwCurrent = i; @@ -429,7 +443,7 @@ };
HRESULT -RecycleBin5_Enumerator_Constructor( +RecycleBin5Enum_Constructor( IN IRecycleBin5 *prb, IN HANDLE hInfo, IN HANDLE hInfoMapped,