ReactOS 0.4.16-dev-178-g8ba6102
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 */
31 STDMETHODIMP GetLastModificationTime(FILETIME *pLastModificationTime) override;
32 STDMETHODIMP GetDeletionTime(FILETIME *pDeletionTime) override;
33 STDMETHODIMP GetFileSize(ULARGE_INTEGER *pFileSize) override;
34 STDMETHODIMP GetPhysicalFileSize(ULARGE_INTEGER *pPhysicalFileSize) override;
35 STDMETHODIMP GetAttributes(DWORD *pAttributes) override;
38 STDMETHODIMP Delete() override;
39 STDMETHODIMP Restore() override;
40
41protected:
46};
47
49{
50 TRACE("(%p, %s, %p)\n", this, debugstr_guid(&riid), ppvObject);
51
52 if (!ppvObject)
53 return E_POINTER;
54
56 *ppvObject = static_cast<IRecycleBinFile *>(this);
57 else if (IsEqualIID(riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW))
58 {
62 else
63 return S_FALSE;
64 }
65 else
66 {
67 *ppvObject = NULL;
68 return E_NOINTERFACE;
69 }
70
71 AddRef();
72 return S_OK;
73}
74
75STDMETHODIMP_(ULONG) RecycleBin5File::AddRef()
76{
77 TRACE("(%p)\n", this);
79}
80
82{
83 TRACE("(%p)\n", this);
84 m_recycleBin->Release();
86}
87
88STDMETHODIMP_(ULONG) RecycleBin5File::Release()
89{
90 TRACE("(%p)\n", this);
91 ULONG refCount = InterlockedDecrement(&m_ref);
92 if (refCount == 0)
93 delete this;
94 return refCount;
95}
96
98{
99 TRACE("(%p, %p)\n", this, pLastModificationTime);
100
104
110 NULL,
113 NULL);
116
117 HRESULT hr;
118 if (GetFileTime(hFile, NULL, NULL, pLastModificationTime))
119 hr = S_OK;
120 else
123 return hr;
124}
125
127{
128 TRACE("(%p, %p)\n", this, pDeletionTime);
129 *pDeletionTime = m_deletedFile.DeletionTime;
130 return S_OK;
131}
132
134{
135 TRACE("(%p, %p)\n", this, pFileSize);
136
141 {
142 pFileSize->QuadPart = 0;
143 return S_OK;
144 }
145
149 pFileSize->u.LowPart = ::GetFileSize(hFile, &pFileSize->u.HighPart);
150
151 HRESULT hr;
152 if (pFileSize->u.LowPart != INVALID_FILE_SIZE)
153 hr = S_OK;
154 else
156
158 return hr;
159}
160
162{
163 TRACE("(%p, %p)\n", this, pPhysicalFileSize);
164 pPhysicalFileSize->u.HighPart = 0;
165 pPhysicalFileSize->u.LowPart = m_deletedFile.dwPhysicalFileSize;
166 return S_OK;
167}
168
170{
172
173 TRACE("(%p, %p)\n", this, pAttributes);
174
178
179 *pAttributes = dwAttributes;
180 return S_OK;
181}
182
184{
185 DWORD dwRequired;
186
187 TRACE("(%p, %u, %p, %p)\n", this, BufferSize, Buffer, RequiredSize);
188
189 dwRequired = (DWORD)(wcslen(m_deletedFile.FileNameW) + 1) * sizeof(WCHAR);
190 if (RequiredSize)
191 *RequiredSize = dwRequired;
192
193 if (BufferSize == 0 && !Buffer)
194 return S_OK;
195
196 if (BufferSize < dwRequired)
197 return E_OUTOFMEMORY;
199 return S_OK;
200}
201
203{
204 HRESULT hr;
205 DWORD dwRequired;
207 SHFILEINFOW shFileInfo;
208
209 TRACE("(%p, %u, %p, %p)\n", this, BufferSize, Buffer, RequiredSize);
210
212 if (!SUCCEEDED(hr))
213 return hr;
214
215 hr = SHGetFileInfoW(m_FullName, dwAttributes, &shFileInfo, sizeof(shFileInfo), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES);
216 if (!SUCCEEDED(hr))
217 return hr;
218
219 dwRequired = (DWORD)(wcslen(shFileInfo.szTypeName) + 1) * sizeof(WCHAR);
220 if (RequiredSize)
221 *RequiredSize = dwRequired;
222
223 if (BufferSize == 0 && !Buffer)
224 return S_OK;
225
226 if (BufferSize < dwRequired)
227 return E_OUTOFMEMORY;
228 CopyMemory(Buffer, shFileInfo.szTypeName, dwRequired);
229 return S_OK;
230}
231
233{
234 TRACE("(%p)\n", this);
235 return m_recycleBin->Delete(m_FullName, &m_deletedFile);
236}
237
239{
240 TRACE("(%p)\n", this);
241 return m_recycleBin->Restore(m_FullName, &m_deletedFile);
242}
243
245 : m_ref(1)
246 , m_recycleBin(NULL)
247 , m_FullName(NULL)
248{
250}
251
254 _In_ IRecycleBin5 *prb,
255 _In_ LPCWSTR Folder,
256 _In_ PDELETED_FILE_RECORD pDeletedFile)
257{
258 m_recycleBin = prb;
259 m_recycleBin->AddRef();
260 m_deletedFile = *pDeletedFile;
261
262 WCHAR szUniqueId[32];
263 StringCchPrintfW(szUniqueId, _countof(szUniqueId), L"%lu", pDeletedFile->dwRecordUniqueId);
264
265 CStringW strFullName(Folder);
266 strFullName += L"\\D";
267 strFullName += (WCHAR)(L'a' + pDeletedFile->dwDriveNumber);
268 strFullName += szUniqueId;
269 strFullName += PathFindExtensionW(pDeletedFile->FileNameW);
271 return E_FAIL;
272
273 return SHStrDup(strFullName, &m_FullName);
274}
275
276static HRESULT
278 _In_ IRecycleBin5 *prb,
279 _In_ LPCWSTR Folder,
280 _In_ PDELETED_FILE_RECORD pDeletedFile,
281 _Out_ IRecycleBinFile **ppFile)
282{
283 if (!ppFile)
284 return E_POINTER;
285
286 *ppFile = NULL;
287
288 RecycleBin5File *pThis = new RecycleBin5File();
289 if (!pThis)
290 return E_OUTOFMEMORY;
291
292 HRESULT hr = pThis->Init(prb, Folder, pDeletedFile);
293 if (FAILED(hr))
294 {
295 delete pThis;
296 return hr;
297 }
298
299 *ppFile = static_cast<IRecycleBinFile *>(pThis);
300 return S_OK;
301}
302
303class RecycleBin5Enum : public IRecycleBinEnumList
304{
305public:
307 virtual ~RecycleBin5Enum();
308
310 _In_ IRecycleBin5 *prb,
311 _In_ HANDLE hInfo,
312 _In_ HANDLE hInfoMapped,
313 _In_ LPCWSTR pszPrefix);
314
315 /* IUnknown methods */
319
320 /* IRecycleBinEnumList methods */
321 STDMETHODIMP Next(DWORD celt, IRecycleBinFile **rgelt, DWORD *pceltFetched) override;
322 STDMETHODIMP Skip(DWORD celt) override;
323 STDMETHODIMP Reset() override;
324
325protected:
332};
333
335{
336 TRACE("(%p, %s, %p)\n", this, debugstr_guid(&riid), ppvObject);
337
338 if (!ppvObject)
339 return E_POINTER;
340
342 *ppvObject = static_cast<IRecycleBinEnumList *>(this);
343 else
344 {
345 *ppvObject = NULL;
346 return E_NOINTERFACE;
347 }
348
349 AddRef();
350 return S_OK;
351}
352
353STDMETHODIMP_(ULONG) RecycleBin5Enum::AddRef()
354{
355 TRACE("(%p)\n", this);
357}
358
360{
361 TRACE("(%p)\n", this);
362
363 m_recycleBin->OnClosing(this);
365 m_recycleBin->Release();
367}
368
369STDMETHODIMP_(ULONG) RecycleBin5Enum::Release()
370{
371 TRACE("(%p)\n", this);
372
373 ULONG refCount = InterlockedDecrement(&m_ref);
374 if (refCount == 0)
375 delete this;
376 return refCount;
377}
378
379STDMETHODIMP RecycleBin5Enum::Next(DWORD celt, IRecycleBinFile **rgelt, DWORD *pceltFetched)
380{
381 HRESULT hr;
382
383 TRACE("(%p, %u, %p, %p)\n", this, celt, rgelt, pceltFetched);
384
385 if (!rgelt)
386 return E_POINTER;
387 if (!pceltFetched && celt > 1)
388 return E_INVALIDARG;
389
391 FileSize.u.LowPart = GetFileSize(m_hInfo, &FileSize.u.HighPart);
392 if (FileSize.u.LowPart == 0)
394
395 DWORD dwEntries =
396 (DWORD)((FileSize.QuadPart - sizeof(INFO2_HEADER)) / sizeof(DELETED_FILE_RECORD));
397
398 DWORD iEntry = m_dwCurrent, fetched = 0;
399 PDELETED_FILE_RECORD pDeletedFile = (PDELETED_FILE_RECORD)(m_pInfo + 1) + iEntry;
400 for (; iEntry < dwEntries && fetched < celt; ++iEntry)
401 {
402 hr = RecycleBin5File_Constructor(m_recycleBin, m_pszPrefix, pDeletedFile, &rgelt[fetched]);
403 if (SUCCEEDED(hr))
404 fetched++;
405 pDeletedFile++;
406 }
407
408 m_dwCurrent = iEntry;
409 if (pceltFetched)
410 *pceltFetched = fetched;
411 if (fetched == celt)
412 return S_OK;
413 else
414 return S_FALSE;
415}
416
418{
419 TRACE("(%p, %u)\n", this, celt);
420 m_dwCurrent += celt;
421 return S_OK;
422}
423
425{
426 TRACE("(%p)\n", this);
427 m_dwCurrent = 0;
428 return S_OK;
429}
430
432 : m_ref(1)
433 , m_recycleBin(NULL)
434 , m_hInfo(NULL)
435 , m_pInfo(NULL)
436 , m_dwCurrent(0)
437 , m_pszPrefix(NULL)
438{
439}
440
443 _In_ IRecycleBin5 *prb,
444 _In_ HANDLE hInfo,
445 _In_ HANDLE hInfoMapped,
446 _In_ LPCWSTR pszPrefix)
447{
448 m_recycleBin = prb;
449 m_recycleBin->AddRef();
450
451 HRESULT hr = SHStrDup(pszPrefix, &m_pszPrefix);
452 if (FAILED(hr))
453 return hr;
454
455 m_hInfo = hInfo;
456 m_pInfo = (PINFO2_HEADER)MapViewOfFile(hInfoMapped, FILE_MAP_READ, 0, 0, 0);
457 if (!m_pInfo)
459
461 return E_FAIL;
462
463 return S_OK;
464}
465
469 _In_ IRecycleBin5 *prb,
470 _In_ HANDLE hInfo,
471 _In_ HANDLE hInfoMapped,
472 _In_ LPCWSTR szPrefix,
473 _Out_ IUnknown **ppUnknown)
474{
475 if (!ppUnknown)
476 return E_POINTER;
477
478 *ppUnknown = NULL;
479
480 RecycleBin5Enum *pThis = new RecycleBin5Enum();
481 if (!pThis)
482 return E_OUTOFMEMORY;
483
484 HRESULT hr = pThis->Init(prb, hInfo, hInfoMapped, szPrefix);
485 if (FAILED(hr))
486 {
487 delete pThis;
488 return hr;
489 }
490
491 *ppUnknown = static_cast<IRecycleBinEnumList *>(pThis);
492 return S_OK;
493}
EXTERN_C HRESULT WINAPI SHCreateFileExtractIconW(_In_ LPCWSTR pszFile, _In_ DWORD dwFileAttributes, _In_ REFIID riid, _Outptr_ void **ppv)
#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 GetTypeName(SIZE_T BufferSize, LPWSTR Buffer, SIZE_T *RequiredSize) 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 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 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
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
_In_ HANDLE hFile
Definition: mswsock.h:90
#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
EXTERN_C const IID IID_IRecycleBinFile
Definition: recyclebin.h:244
EXTERN_C const IID IID_IRecycleBinEnumList
Definition: recyclebin.h:245
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)
DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path, DWORD dwFileAttributes, SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
Definition: shell32_main.c:414
#define SHGFI_TYPENAME
Definition: shellapi.h:167
#define SHGFI_USEFILEATTRIBUTES
Definition: shellapi.h:181
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
WCHAR FileNameW[MAX_PATH]
Definition: recyclebin_v5.h:20
WCHAR szTypeName[80]
Definition: shellapi.h:376
struct _ULARGE_INTEGER::@4136 u
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
struct _LARGE_INTEGER::@2299 u
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:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define CopyMemory
Definition: winbase.h:1710
#define INVALID_FILE_SIZE
Definition: winbase.h:548
_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