mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-03 12:23:25 +00:00
Better compatibility with MS Windows recycle bin
Add traces svn path=/trunk/; revision=30811
This commit is contained in:
@@ -4,7 +4,6 @@ It is aimed to be compatible with Windows 2000/XP/2003 (at least) on FAT or NTFS
|
||||
TODO
|
||||
- Empty a recycle bin containing directories (v5)
|
||||
- Set security on recycle bin folder
|
||||
- Delete files > 4Gb
|
||||
- Make the library thread-safe
|
||||
|
||||
3 levels
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "recyclebin_private.h"
|
||||
#include <stdio.h>
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(recyclebin);
|
||||
|
||||
BOOL WINAPI
|
||||
CloseRecycleBinHandle(
|
||||
IN HANDLE hDeletedFile)
|
||||
@@ -17,6 +19,8 @@ CloseRecycleBinHandle(
|
||||
IRecycleBinFile *rbf = (IRecycleBinFile *)hDeletedFile;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p)\n", hDeletedFile);
|
||||
|
||||
hr = IRecycleBinFile_Release(rbf);
|
||||
if (SUCCEEDED(hr))
|
||||
return TRUE;
|
||||
@@ -35,6 +39,8 @@ DeleteFileToRecycleBinA(
|
||||
LPWSTR FileNameW = NULL;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("(%s)\n", debugstr_a(FileName));
|
||||
|
||||
/* Check parameters */
|
||||
if (FileName == NULL)
|
||||
{
|
||||
@@ -68,6 +74,8 @@ DeleteFileToRecycleBinW(
|
||||
IRecycleBin *prb;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%s)\n", debugstr_w(FileName));
|
||||
|
||||
hr = GetDefaultRecycleBin(NULL, &prb);
|
||||
if (!SUCCEEDED(hr))
|
||||
goto cleanup;
|
||||
@@ -93,6 +101,8 @@ EmptyRecycleBinA(
|
||||
LPWSTR szRootW = NULL;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("(%s)\n", debugstr_a(pszRoot));
|
||||
|
||||
if (pszRoot)
|
||||
{
|
||||
len = MultiByteToWideChar(CP_ACP, 0, pszRoot, -1, NULL, 0);
|
||||
@@ -122,6 +132,8 @@ EmptyRecycleBinW(
|
||||
IRecycleBin *prb;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%s)\n", debugstr_w(pszRoot));
|
||||
|
||||
hr = GetDefaultRecycleBin(pszRoot, &prb);
|
||||
if (!SUCCEEDED(hr))
|
||||
goto cleanup;
|
||||
@@ -149,6 +161,8 @@ EnumerateRecycleBinA(
|
||||
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);
|
||||
@@ -182,6 +196,8 @@ EnumerateRecycleBinW(
|
||||
IRecycleBinFile *prbf;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%s, %p, %p)\n", debugstr_w(pszRoot), pFnCallback, Context);
|
||||
|
||||
hr = GetDefaultRecycleBin(NULL, &prb);
|
||||
if (!SUCCEEDED(hr))
|
||||
goto cleanup;
|
||||
@@ -231,6 +247,8 @@ GetDeletedFileDetailsA(
|
||||
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 @@ GetDeletedFileDetailsW(
|
||||
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 @@ RestoreFile(
|
||||
IRecycleBinFile *rbf = (IRecycleBinFile *)hDeletedFile;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p)\n", hDeletedFile);
|
||||
|
||||
hr = IRecycleBinFile_Restore(rbf);
|
||||
if (SUCCEEDED(hr))
|
||||
return TRUE;
|
||||
@@ -339,6 +361,8 @@ GetDefaultRecycleBin(
|
||||
IUnknown *pUnk;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%s, %p)\n", debugstr_w(pszVolume), pprb);
|
||||
|
||||
if (!pprb)
|
||||
return E_POINTER;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ struct RecycleBinGeneric
|
||||
};
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
RecycleBinGenericVtbl_RecycleBin_QueryInterface(
|
||||
RecycleBinGeneric_RecycleBin_QueryInterface(
|
||||
IRecycleBin *This,
|
||||
REFIID riid,
|
||||
void **ppvObject)
|
||||
@@ -46,7 +46,7 @@ RecycleBinGenericVtbl_RecycleBin_QueryInterface(
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE
|
||||
RecycleBinGenericVtbl_RecycleBin_AddRef(
|
||||
RecycleBinGeneric_RecycleBin_AddRef(
|
||||
IRecycleBin *This)
|
||||
{
|
||||
struct RecycleBinGeneric *s = CONTAINING_RECORD(This, struct RecycleBinGeneric, recycleBinImpl);
|
||||
@@ -55,8 +55,17 @@ RecycleBinGenericVtbl_RecycleBin_AddRef(
|
||||
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 @@ RecycleBinGenericVtbl_RecycleBin_Release(
|
||||
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 @@ RecycleBinGenericVtbl_RecycleBin_DeleteFile(
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
RecycleBinGenericVtbl_RecycleBin_EmptyRecycleBin(
|
||||
RecycleBinGeneric_RecycleBin_EmptyRecycleBin(
|
||||
IN IRecycleBin *This)
|
||||
{
|
||||
WCHAR szVolumeName[MAX_PATH];
|
||||
@@ -161,7 +170,7 @@ RecycleBinGenericVtbl_RecycleBin_EmptyRecycleBin(
|
||||
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 @@ RecycleBinGenericVtbl_RecycleBin_EmptyRecycleBin(
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -58,6 +58,17 @@ RecycleBinGenericEnum_RecycleBinEnumList_AddRef(
|
||||
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 @@ RecycleBinGenericEnum_RecycleBinEnumList_Release(
|
||||
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 @@ CONST_VTBL struct IRecycleBinEnumListVtbl RecycleBinGenericEnumVtbl =
|
||||
};
|
||||
|
||||
HRESULT
|
||||
RecycleBinGeneric_Enumerator_Constructor(
|
||||
RecycleBinGenericEnum_Constructor(
|
||||
OUT IRecycleBinEnumList **pprbel)
|
||||
{
|
||||
struct RecycleBinGenericEnum *s;
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#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"
|
||||
@@ -12,13 +10,6 @@
|
||||
|
||||
#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 */
|
||||
|
||||
#include <pshpack1.h>
|
||||
@@ -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 @@ HRESULT RecycleBinGeneric_Constructor(OUT IUnknown **ppUnknown);
|
||||
|
||||
/* recyclebin_generic_enumerator.c */
|
||||
|
||||
HRESULT RecycleBinGeneric_Enumerator_Constructor(OUT IRecycleBinEnumList **pprbel);
|
||||
HRESULT RecycleBinGenericEnum_Constructor(OUT IRecycleBinEnumList **pprbel);
|
||||
|
||||
/* recyclebin_v5.c */
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ struct RecycleBin5
|
||||
};
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
RecycleBin5_RecycleBin5_QueryInterface(
|
||||
RecycleBin5_RecycleBin5_QueryInterface(
|
||||
IRecycleBin5 *This,
|
||||
REFIID riid,
|
||||
void **ppvObject)
|
||||
@@ -105,6 +105,19 @@ RecycleBin5_RecycleBin5_AddRef(
|
||||
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 @@ RecycleBin5_RecycleBin5_Release(
|
||||
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 @@ RecycleBin5_RecycleBin5_DeleteFile(
|
||||
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 @@ RecycleBin5_RecycleBin5_DeleteFile(
|
||||
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)
|
||||
if (FileSize.u.HighPart != 0)
|
||||
{
|
||||
/* FIXME: how to delete files >= 4Gb? */
|
||||
hr = E_NOTIMPL;
|
||||
/* Yes, this recyclebin can't support this file */
|
||||
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
goto cleanup;
|
||||
}
|
||||
pHeader->dwTotalLogicalSize += fileSize.u.LowPart;
|
||||
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 @@ RecycleBin5_RecycleBin5_DeleteFile(
|
||||
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 @@ RecycleBin5_RecycleBin5_DeleteFile(
|
||||
SetLastError(ERROR_INVALID_NAME);
|
||||
goto cleanup;
|
||||
}
|
||||
pHeader->dwNumberOfEntries++;
|
||||
|
||||
/* Move file */
|
||||
if (MoveFileW(szFullName, DeletedFileName))
|
||||
@@ -323,7 +345,7 @@ RecycleBin5_RecycleBin5_EnumObjects(
|
||||
|
||||
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 @@ RecycleBin5_RecycleBin5_Delete(
|
||||
|
||||
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 @@ cleanup:
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ interface IRecycleBin5
|
||||
#endif
|
||||
|
||||
HRESULT
|
||||
RecycleBin5_Enumerator_Constructor(
|
||||
RecycleBin5Enum_Constructor(
|
||||
IN IRecycleBin5 *prb,
|
||||
IN HANDLE hInfo,
|
||||
IN HANDLE hInfoMapped,
|
||||
|
||||
@@ -57,6 +57,16 @@ RecycleBin5File_RecycleBinFile_AddRef(
|
||||
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 @@ RecycleBin5File_RecycleBinFile_Release(
|
||||
refCount = InterlockedDecrement((PLONG)&s->ref);
|
||||
|
||||
if (refCount == 0)
|
||||
{
|
||||
IRecycleBin5_Release(s->recycleBin);
|
||||
CoTaskMemFree(s);
|
||||
}
|
||||
RecycleBin5File_Destructor(s);
|
||||
|
||||
return refCount;
|
||||
}
|
||||
@@ -240,7 +247,7 @@ CONST_VTBL struct IRecycleBinFileVtbl RecycleBin5FileVtbl =
|
||||
};
|
||||
|
||||
static HRESULT
|
||||
RecycleBin5_File_Constructor(
|
||||
RecycleBin5File_Constructor(
|
||||
IN IRecycleBin5 *prb,
|
||||
IN LPCWSTR Folder,
|
||||
IN PDELETED_FILE_RECORD pDeletedFile,
|
||||
@@ -272,6 +279,11 @@ RecycleBin5_File_Constructor(
|
||||
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 @@ RecycleBin5Enum_RecycleBinEnumList_AddRef(
|
||||
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 @@ RecycleBin5Enum_RecycleBinEnumList_Release(
|
||||
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 @@ RecycleBin5Enum_RecycleBinEnumList_Next(
|
||||
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 @@ CONST_VTBL struct IRecycleBinEnumListVtbl RecycleBin5EnumVtbl =
|
||||
};
|
||||
|
||||
HRESULT
|
||||
RecycleBin5_Enumerator_Constructor(
|
||||
RecycleBin5Enum_Constructor(
|
||||
IN IRecycleBin5 *prb,
|
||||
IN HANDLE hInfo,
|
||||
IN HANDLE hInfoMapped,
|
||||
|
||||
Reference in New Issue
Block a user