ReactOS 0.4.16-dev-550-g2186ce3
recyclebin_v5_enumerator.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: Recycle bin management
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Enumerates contents of a MS Windows 2000/XP/2003 recyclebin
5 * COPYRIGHT: Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
6 * Copyright 2024 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
7 */
8
10#include <atlstr.h>
11#include <shlwapi.h>
12#include <strsafe.h>
13
14class RecycleBin5File : public IRecycleBinFile
15{
16public:
18 virtual ~RecycleBin5File();
19
21 _In_ IRecycleBin5 *prb,
22 _In_ LPCWSTR Folder,
23 _In_ PDELETED_FILE_RECORD pDeletedFile);
24
25 /* IUnknown methods */
29
30 /* IRecycleBinFile methods */
32 {
35 }
37 STDMETHODIMP GetLastModificationTime(FILETIME *pLastModificationTime) override;
38 STDMETHODIMP GetDeletionTime(FILETIME *pDeletionTime) override;
39 STDMETHODIMP GetFileSize(ULARGE_INTEGER *pFileSize) override;
40 STDMETHODIMP GetPhysicalFileSize(ULARGE_INTEGER *pPhysicalFileSize) override;
41 STDMETHODIMP GetAttributes(DWORD *pAttributes) override;
43 STDMETHODIMP Delete() override;
44 STDMETHODIMP Restore() override;
45
46protected:
51};
52
54{
55 TRACE("(%p, %s, %p)\n", this, debugstr_guid(&riid), ppvObject);
56
57 if (!ppvObject)
58 return E_POINTER;
59
61 {
62 *ppvObject = static_cast<IRecycleBinFile *>(this);
63 }
64 else
65 {
66 *ppvObject = NULL;
67 return E_NOINTERFACE;
68 }
69
70 AddRef();
71 return S_OK;
72}
73
74STDMETHODIMP_(ULONG) RecycleBin5File::AddRef()
75{
76 TRACE("(%p)\n", this);
78}
79
81{
82 TRACE("(%p)\n", this);
83 m_recycleBin->Release();
85}
86
87STDMETHODIMP_(ULONG) RecycleBin5File::Release()
88{
89 TRACE("(%p)\n", this);
90 ULONG refCount = InterlockedDecrement(&m_ref);
91 if (refCount == 0)
92 delete this;
93 return refCount;
94}
95
97{
98 HRESULT hr = S_OK;
101 ZeroMemory(&pInfo->LastModification, sizeof(pInfo->LastModification));
103 C_ASSERT(sizeof(pInfo->FileSize) <= sizeof(UINT));
104 pInfo->FileSize = FAILED(GetFileSize(&uli)) ? INVALID_FILE_SIZE : uli.LowPart;
105 if (FAILED(hr = GetAttributes(&pInfo->Attributes)))
106 pInfo->Attributes = 0;
109 return hr;
110}
111
113{
114 TRACE("(%p, %p)\n", this, pLastModificationTime);
115
119
125 NULL,
128 NULL);
131
132 HRESULT hr;
133 if (GetFileTime(hFile, NULL, NULL, pLastModificationTime))
134 hr = S_OK;
135 else
138 return hr;
139}
140
142{
143 TRACE("(%p, %p)\n", this, pDeletionTime);
144 *pDeletionTime = m_deletedFile.DeletionTime;
145 return S_OK;
146}
147
149{
150 TRACE("(%p, %p)\n", this, pFileSize);
151
156 {
157 pFileSize->QuadPart = 0;
158 return S_OK;
159 }
160
164 pFileSize->u.LowPart = ::GetFileSize(hFile, &pFileSize->u.HighPart);
165
166 HRESULT hr;
167 if (pFileSize->u.LowPart != INVALID_FILE_SIZE)
168 hr = S_OK;
169 else
171
173 return hr;
174}
175
177{
178 TRACE("(%p, %p)\n", this, pPhysicalFileSize);
179 pPhysicalFileSize->u.HighPart = 0;
180 pPhysicalFileSize->u.LowPart = m_deletedFile.dwPhysicalFileSize;
181 return S_OK;
182}
183
185{
187
188 TRACE("(%p, %p)\n", this, pAttributes);
189
193
194 *pAttributes = dwAttributes;
195 return S_OK;
196}
197
199{
200 DWORD dwRequired;
201
202 TRACE("(%p, %u, %p, %p)\n", this, BufferSize, Buffer, RequiredSize);
203
204 dwRequired = (DWORD)(wcslen(m_deletedFile.FileNameW) + 1) * sizeof(WCHAR);
205 if (RequiredSize)
206 *RequiredSize = dwRequired;
207
208 if (BufferSize == 0 && !Buffer)
209 return S_OK;
210
211 if (BufferSize < dwRequired)
212 return E_OUTOFMEMORY;
214 return S_OK;
215}
216
218{
219 TRACE("(%p)\n", this);
220 return m_recycleBin->Delete(m_FullName, &m_deletedFile);
221}
222
224{
225 TRACE("(%p)\n", this);
226 return m_recycleBin->Restore(m_FullName, &m_deletedFile);
227}
228
230 : m_ref(1)
231 , m_recycleBin(NULL)
232 , m_FullName(NULL)
233{
235}
236
239 _In_ IRecycleBin5 *prb,
240 _In_ LPCWSTR Folder,
241 _In_ PDELETED_FILE_RECORD pDeletedFile)
242{
243 m_recycleBin = prb;
244 m_recycleBin->AddRef();
245 m_deletedFile = *pDeletedFile;
246
247 WCHAR szUniqueId[32];
248 StringCchPrintfW(szUniqueId, _countof(szUniqueId), L"%lu", pDeletedFile->dwRecordUniqueId);
249
250 CStringW strFullName(Folder);
251 strFullName += L"\\D";
252 strFullName += (WCHAR)(L'a' + pDeletedFile->dwDriveNumber);
253 strFullName += szUniqueId;
254 strFullName += PathFindExtensionW(pDeletedFile->FileNameW);
256 return E_FAIL;
257
258 return SHStrDup(strFullName, &m_FullName);
259}
260
261static HRESULT
263 _In_ IRecycleBin5 *prb,
264 _In_ LPCWSTR Folder,
265 _In_ PDELETED_FILE_RECORD pDeletedFile,
266 _Out_ IRecycleBinFile **ppFile)
267{
268 if (!ppFile)
269 return E_POINTER;
270
271 *ppFile = NULL;
272
273 RecycleBin5File *pThis = new RecycleBin5File();
274 if (!pThis)
275 return E_OUTOFMEMORY;
276
277 HRESULT hr = pThis->Init(prb, Folder, pDeletedFile);
278 if (FAILED(hr))
279 {
280 delete pThis;
281 return hr;
282 }
283
284 *ppFile = static_cast<IRecycleBinFile *>(pThis);
285 return S_OK;
286}
287
288class RecycleBin5Enum : public IRecycleBinEnumList
289{
290public:
292 virtual ~RecycleBin5Enum();
293
295 _In_ IRecycleBin5 *prb,
296 _In_ HANDLE hInfo,
297 _In_ HANDLE hInfoMapped,
298 _In_ LPCWSTR pszPrefix);
299
300 /* IUnknown methods */
304
305 /* IRecycleBinEnumList methods */
306 STDMETHODIMP Next(DWORD celt, IRecycleBinFile **rgelt, DWORD *pceltFetched) override;
307 STDMETHODIMP Skip(DWORD celt) override;
308 STDMETHODIMP Reset() override;
309
310protected:
317};
318
320{
321 TRACE("(%p, %s, %p)\n", this, debugstr_guid(&riid), ppvObject);
322
323 if (!ppvObject)
324 return E_POINTER;
325
327 *ppvObject = static_cast<IRecycleBinEnumList *>(this);
328 else
329 {
330 *ppvObject = NULL;
331 return E_NOINTERFACE;
332 }
333
334 AddRef();
335 return S_OK;
336}
337
338STDMETHODIMP_(ULONG) RecycleBin5Enum::AddRef()
339{
340 TRACE("(%p)\n", this);
342}
343
345{
346 TRACE("(%p)\n", this);
347
348 m_recycleBin->OnClosing(this);
350 m_recycleBin->Release();
352}
353
354STDMETHODIMP_(ULONG) RecycleBin5Enum::Release()
355{
356 TRACE("(%p)\n", this);
357
358 ULONG refCount = InterlockedDecrement(&m_ref);
359 if (refCount == 0)
360 delete this;
361 return refCount;
362}
363
364STDMETHODIMP RecycleBin5Enum::Next(DWORD celt, IRecycleBinFile **rgelt, DWORD *pceltFetched)
365{
366 HRESULT hr;
367
368 TRACE("(%p, %u, %p, %p)\n", this, celt, rgelt, pceltFetched);
369
370 if (!rgelt)
371 return E_POINTER;
372 if (!pceltFetched && celt > 1)
373 return E_INVALIDARG;
374
376 FileSize.u.LowPart = GetFileSize(m_hInfo, &FileSize.u.HighPart);
377 if (FileSize.u.LowPart == 0)
379
380 DWORD dwEntries =
381 (DWORD)((FileSize.QuadPart - sizeof(INFO2_HEADER)) / sizeof(DELETED_FILE_RECORD));
382
383 DWORD iEntry = m_dwCurrent, fetched = 0;
384 PDELETED_FILE_RECORD pDeletedFile = (PDELETED_FILE_RECORD)(m_pInfo + 1) + iEntry;
385 for (; iEntry < dwEntries && fetched < celt; ++iEntry)
386 {
387 hr = RecycleBin5File_Constructor(m_recycleBin, m_pszPrefix, pDeletedFile, &rgelt[fetched]);
388 if (SUCCEEDED(hr))
389 fetched++;
390 pDeletedFile++;
391 }
392
393 m_dwCurrent = iEntry;
394 if (pceltFetched)
395 *pceltFetched = fetched;
396 if (fetched == celt)
397 return S_OK;
398 else
399 return S_FALSE;
400}
401
403{
404 TRACE("(%p, %u)\n", this, celt);
405 m_dwCurrent += celt;
406 return S_OK;
407}
408
410{
411 TRACE("(%p)\n", this);
412 m_dwCurrent = 0;
413 return S_OK;
414}
415
417 : m_ref(1)
418 , m_recycleBin(NULL)
419 , m_hInfo(NULL)
420 , m_pInfo(NULL)
421 , m_dwCurrent(0)
422 , m_pszPrefix(NULL)
423{
424}
425
428 _In_ IRecycleBin5 *prb,
429 _In_ HANDLE hInfo,
430 _In_ HANDLE hInfoMapped,
431 _In_ LPCWSTR pszPrefix)
432{
433 m_recycleBin = prb;
434 m_recycleBin->AddRef();
435
436 HRESULT hr = SHStrDup(pszPrefix, &m_pszPrefix);
437 if (FAILED(hr))
438 return hr;
439
440 m_hInfo = hInfo;
441 m_pInfo = (PINFO2_HEADER)MapViewOfFile(hInfoMapped, FILE_MAP_READ, 0, 0, 0);
442 if (!m_pInfo)
444
446 return E_FAIL;
447
448 return S_OK;
449}
450
454 _In_ IRecycleBin5 *prb,
455 _In_ HANDLE hInfo,
456 _In_ HANDLE hInfoMapped,
457 _In_ LPCWSTR szPrefix,
458 _Out_ IUnknown **ppUnknown)
459{
460 if (!ppUnknown)
461 return E_POINTER;
462
463 *ppUnknown = NULL;
464
465 RecycleBin5Enum *pThis = new RecycleBin5Enum();
466 if (!pThis)
467 return E_OUTOFMEMORY;
468
469 HRESULT hr = pThis->Init(prb, hInfo, hInfoMapped, szPrefix);
470 if (FAILED(hr))
471 {
472 delete pThis;
473 return hr;
474 }
475
476 *ppUnknown = static_cast<IRecycleBinEnumList *>(pThis);
477 return S_OK;
478}
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define EXTERN_C
Definition: basetyps.h:12
#define STDMETHODIMP
Definition: basetyps.h:43
#define STDMETHODIMP_(t)
Definition: basetyps.h:44
const GUID IID_IUnknown
_In_ BOOLEAN Release
Definition: cdrom.h:920
Definition: bufpool.h:45
STDMETHODIMP Reset() override
STDMETHODIMP Next(DWORD celt, IRecycleBinFile **rgelt, DWORD *pceltFetched) override
STDMETHODIMP Skip(DWORD celt) override
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override
HRESULT Init(_In_ IRecycleBin5 *prb, _In_ HANDLE hInfo, _In_ HANDLE hInfoMapped, _In_ LPCWSTR pszPrefix)
STDMETHODIMP_(ULONG) AddRef() override
STDMETHODIMP_(ULONG) Release() override
STDMETHODIMP IsEqualIdentity(const RECYCLEBINFILEIDENTITY *pFI) override
STDMETHODIMP GetFileSize(ULARGE_INTEGER *pFileSize) override
STDMETHODIMP GetPhysicalFileSize(ULARGE_INTEGER *pPhysicalFileSize) override
HRESULT Init(_In_ IRecycleBin5 *prb, _In_ LPCWSTR Folder, _In_ PDELETED_FILE_RECORD pDeletedFile)
STDMETHODIMP_(ULONG) Release() override
STDMETHODIMP GetAttributes(DWORD *pAttributes) override
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override
DELETED_FILE_RECORD m_deletedFile
STDMETHODIMP Restore() override
STDMETHODIMP GetInfo(PDELETED_FILE_INFO pInfo) override
STDMETHODIMP Delete() override
STDMETHODIMP GetDeletionTime(FILETIME *pDeletionTime) override
STDMETHODIMP GetFileName(SIZE_T BufferSize, LPWSTR Buffer, SIZE_T *RequiredSize) override
STDMETHODIMP_(ULONG) AddRef() override
STDMETHODIMP GetLastModificationTime(FILETIME *pLastModificationTime) override
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define CloseHandle
Definition: compat.h:739
#define UnmapViewOfFile
Definition: compat.h:746
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define CreateFileW
Definition: compat.h:741
#define FILE_MAP_READ
Definition: compat.h:776
#define MapViewOfFile
Definition: compat.h:745
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
BOOL WINAPI GetFileTime(IN HANDLE hFile, OUT LPFILETIME lpCreationTime OPTIONAL, OUT LPFILETIME lpLastAccessTime OPTIONAL, OUT LPFILETIME lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:896
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:326
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:447
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define C_ASSERT(e)
Definition: intsafe.h:73
#define debugstr_guid
Definition: kernel32.h:35
#define FILE_FLAG_BACKUP_SEMANTICS
Definition: disk.h:41
static ULONG WINAPI AddRef(IStream *iface)
Definition: clist.c:90
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define DWORD
Definition: nt_native.h:44
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
static void InitializeRecycleBinStringRef(PRECYCLEBINSTRING pRBS, LPCWSTR String)
Definition: recyclebin.h:62
EXTERN_C const IID IID_IRecycleBinFile
Definition: recyclebin.h:234
EXTERN_C const IID IID_IRecycleBinEnumList
Definition: recyclebin.h:235
EXTERN_C BOOL RecycleBinGeneric_IsEqualFileIdentity(const RECYCLEBINFILEIDENTITY *p1, const RECYCLEBINFILEIDENTITY *p2)
struct _INFO2_HEADER * PINFO2_HEADER
struct _DELETED_FILE_RECORD * PDELETED_FILE_RECORD
interface IRecycleBin5 IRecycleBin5
Definition: recyclebin_v5.h:27
struct _DELETED_FILE_RECORD DELETED_FILE_RECORD
static HRESULT RecycleBin5File_Constructor(_In_ IRecycleBin5 *prb, _In_ LPCWSTR Folder, _In_ PDELETED_FILE_RECORD pDeletedFile, _Out_ IRecycleBinFile **ppFile)
EXTERN_C HRESULT RecycleBin5Enum_Constructor(_In_ IRecycleBin5 *prb, _In_ HANDLE hInfo, _In_ HANDLE hInfoMapped, _In_ LPCWSTR szPrefix, _Out_ IUnknown **ppUnknown)
HRESULT HResultFromWin32(DWORD hr)
Definition: shellutils.h:70
HRESULT hr
Definition: shlfolder.c:183
#define SHStrDup
Definition: shlwapi.h:1563
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
RECYCLEBINFILESIZETYPE FileSize
Definition: recyclebin.h:42
RECYCLEBINSTRING RecycledFullPath
Definition: recyclebin.h:45
FILETIME DeletionTime
Definition: recyclebin.h:41
RECYCLEBINSTRING OriginalFullPath
Definition: recyclebin.h:44
FILETIME LastModification
Definition: recyclebin.h:40
WCHAR FileNameW[MAX_PATH]
Definition: recyclebin_v5.h:20
$ULONG LowPart
Definition: ntbasedef.h:577
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
struct _ULARGE_INTEGER::@4177 u
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG
Definition: typedefs.h:59
struct _LARGE_INTEGER::@2306 u
LONGLONG QuadPart
Definition: typedefs.h:114
DWORD dwAttributes
Definition: vdmdbg.h:34
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ ULONG _Out_ PVOID _Out_ PULONG RequiredSize
Definition: wdfdevice.h:4439
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
#define ZeroMemory
Definition: winbase.h:1737
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define CopyMemory
Definition: winbase.h:1735
#define INVALID_FILE_SIZE
Definition: winbase.h:574
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD _Outptr_opt_ void ** ppvObject
Definition: wincrypt.h:6082
#define S_FALSE
Definition: winerror.h:2357
#define E_NOINTERFACE
Definition: winerror.h:2364
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define E_POINTER
Definition: winerror.h:2365
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185