mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
[SHELL32] RecycleBinGenericEnum: Make it C++ (#7167)
Modernize code. JIRA issue: CORE-19595 Rewrite RecycleBinGenericEnum in C++.
This commit is contained in:
parent
d5aca44042
commit
72116d0558
5 changed files with 222 additions and 235 deletions
|
@ -7,7 +7,7 @@ add_definitions(
|
|||
list(APPEND SOURCE
|
||||
recyclebin.c
|
||||
recyclebin_generic.c
|
||||
recyclebin_generic_enumerator.c
|
||||
recyclebin_generic_enumerator.cpp
|
||||
recyclebin_v5.c
|
||||
recyclebin_v5_enumerator.c
|
||||
recyclebin_private.h)
|
||||
|
|
|
@ -214,7 +214,7 @@ DECLARE_INTERFACE_(IRecycleBinEnumList, IUnknown)
|
|||
STDMETHOD_(ULONG, Release)(THIS) PURE;
|
||||
|
||||
/* IRecycleBinEnumList methods */
|
||||
STDMETHOD(Next)(THIS_ DWORD celt, IRecycleBinFile **rgelt, DWORD *pceltFetched);
|
||||
STDMETHOD(Next)(THIS_ DWORD celt, IRecycleBinFile **rgelt, DWORD *pceltFetched) PURE;
|
||||
STDMETHOD(Skip)(THIS_ DWORD celt) PURE;
|
||||
STDMETHOD(Reset)(THIS) PURE;
|
||||
|
||||
|
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
* PROJECT: Recycle bin management
|
||||
* LICENSE: GPL v2 - See COPYING in the top level directory
|
||||
* FILE: lib/recyclebin/recyclebin_generic_enumerator.c
|
||||
* PURPOSE: Enumerates contents of all recycle bins
|
||||
* PROGRAMMERS: Copyright 2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||
*/
|
||||
|
||||
#include "recyclebin_private.h"
|
||||
|
||||
struct RecycleBinGenericEnum
|
||||
{
|
||||
ULONG ref;
|
||||
IRecycleBinEnumList recycleBinEnumImpl;
|
||||
IRecycleBinEnumList *current;
|
||||
DWORD dwLogicalDrives;
|
||||
SIZE_T skip;
|
||||
};
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_QueryInterface(
|
||||
IN IRecycleBinEnumList *This,
|
||||
IN REFIID riid,
|
||||
OUT void **ppvObject)
|
||||
{
|
||||
struct RecycleBinGenericEnum *s = CONTAINING_RECORD(This, struct RecycleBinGenericEnum, recycleBinEnumImpl);
|
||||
|
||||
TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObject);
|
||||
|
||||
if (!ppvObject)
|
||||
return E_POINTER;
|
||||
|
||||
if (IsEqualIID(riid, &IID_IUnknown))
|
||||
*ppvObject = &s->recycleBinEnumImpl;
|
||||
else if (IsEqualIID(riid, &IID_IRecycleBinEnumList))
|
||||
*ppvObject = &s->recycleBinEnumImpl;
|
||||
else
|
||||
{
|
||||
*ppvObject = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
IUnknown_AddRef(This);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_AddRef(
|
||||
IN IRecycleBinEnumList *This)
|
||||
{
|
||||
struct RecycleBinGenericEnum *s = CONTAINING_RECORD(This, struct RecycleBinGenericEnum, recycleBinEnumImpl);
|
||||
ULONG refCount = InterlockedIncrement((PLONG)&s->ref);
|
||||
TRACE("(%p)\n", This);
|
||||
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)
|
||||
{
|
||||
struct RecycleBinGenericEnum *s = CONTAINING_RECORD(This, struct RecycleBinGenericEnum, recycleBinEnumImpl);
|
||||
ULONG refCount;
|
||||
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
refCount = InterlockedDecrement((PLONG)&s->ref);
|
||||
|
||||
if (refCount == 0)
|
||||
RecycleBinGenericEnum_Destructor(s);
|
||||
|
||||
return refCount;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_Next(
|
||||
IN IRecycleBinEnumList *This,
|
||||
IN DWORD celt,
|
||||
IN OUT IRecycleBinFile **rgelt,
|
||||
OUT DWORD *pceltFetched)
|
||||
{
|
||||
struct RecycleBinGenericEnum *s = CONTAINING_RECORD(This, struct RecycleBinGenericEnum, recycleBinEnumImpl);
|
||||
IRecycleBin *prb;
|
||||
DWORD i;
|
||||
DWORD fetched = 0, newFetched;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p, %u, %p, %p)\n", This, celt, rgelt, pceltFetched);
|
||||
|
||||
if (!rgelt)
|
||||
return E_POINTER;
|
||||
if (!pceltFetched && celt > 1)
|
||||
return E_INVALIDARG;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
/* Get enumerator implementation */
|
||||
if (!s->current && s->dwLogicalDrives)
|
||||
{
|
||||
for (i = 0; i < 26; i++)
|
||||
if (s->dwLogicalDrives & (1 << i))
|
||||
{
|
||||
WCHAR szVolumeName[4];
|
||||
szVolumeName[0] = (WCHAR)('A' + i);
|
||||
szVolumeName[1] = ':';
|
||||
szVolumeName[2] = '\\';
|
||||
szVolumeName[3] = UNICODE_NULL;
|
||||
if (GetDriveTypeW(szVolumeName) != DRIVE_FIXED)
|
||||
{
|
||||
s->dwLogicalDrives &= ~(1 << i);
|
||||
continue;
|
||||
}
|
||||
hr = GetDefaultRecycleBin(szVolumeName, &prb);
|
||||
if (!SUCCEEDED(hr))
|
||||
return hr;
|
||||
hr = IRecycleBin_EnumObjects(prb, &s->current);
|
||||
IRecycleBin_Release(prb);
|
||||
if (!SUCCEEDED(hr))
|
||||
return hr;
|
||||
s->dwLogicalDrives &= ~(1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!s->current)
|
||||
{
|
||||
/* Nothing more to enumerate */
|
||||
if (pceltFetched)
|
||||
*pceltFetched = fetched;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
/* Skip some elements */
|
||||
while (s->skip > 0)
|
||||
{
|
||||
IRecycleBinFile *rbf;
|
||||
hr = IRecycleBinEnumList_Next(s->current, 1, &rbf, NULL);
|
||||
if (hr == S_OK)
|
||||
hr = IRecycleBinFile_Release(rbf);
|
||||
else if (hr == S_FALSE)
|
||||
break;
|
||||
else if (!SUCCEEDED(hr))
|
||||
return hr;
|
||||
}
|
||||
if (s->skip > 0)
|
||||
continue;
|
||||
|
||||
/* Fill area */
|
||||
hr = IRecycleBinEnumList_Next(s->current, celt - fetched, &rgelt[fetched], &newFetched);
|
||||
if (SUCCEEDED(hr))
|
||||
fetched += newFetched;
|
||||
if (hr == S_FALSE || newFetched == 0)
|
||||
{
|
||||
hr = IRecycleBinEnumList_Release(s->current);
|
||||
s->current = NULL;
|
||||
}
|
||||
else if (!SUCCEEDED(hr))
|
||||
return hr;
|
||||
if (fetched == celt)
|
||||
{
|
||||
if (pceltFetched)
|
||||
*pceltFetched = fetched;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Never go here */
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_Skip(
|
||||
IN IRecycleBinEnumList *This,
|
||||
IN DWORD celt)
|
||||
{
|
||||
struct RecycleBinGenericEnum *s = CONTAINING_RECORD(This, struct RecycleBinGenericEnum, recycleBinEnumImpl);
|
||||
TRACE("(%p, %u)\n", This, celt);
|
||||
s->skip += celt;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_Reset(
|
||||
IN IRecycleBinEnumList *This)
|
||||
{
|
||||
struct RecycleBinGenericEnum *s = CONTAINING_RECORD(This, struct RecycleBinGenericEnum, recycleBinEnumImpl);
|
||||
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
if (s->current)
|
||||
{
|
||||
IRecycleBinEnumList_Release(s->current);
|
||||
s->current = NULL;
|
||||
s->skip = 0;
|
||||
}
|
||||
s->dwLogicalDrives = GetLogicalDrives();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CONST_VTBL struct IRecycleBinEnumListVtbl RecycleBinGenericEnumVtbl =
|
||||
{
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_QueryInterface,
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_AddRef,
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_Release,
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_Next,
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_Skip,
|
||||
RecycleBinGenericEnum_RecycleBinEnumList_Reset,
|
||||
};
|
||||
|
||||
HRESULT
|
||||
RecycleBinGenericEnum_Constructor(
|
||||
OUT IRecycleBinEnumList **pprbel)
|
||||
{
|
||||
struct RecycleBinGenericEnum *s;
|
||||
|
||||
s = CoTaskMemAlloc(sizeof(struct RecycleBinGenericEnum));
|
||||
if (!s)
|
||||
return E_OUTOFMEMORY;
|
||||
ZeroMemory(s, sizeof(struct RecycleBinGenericEnum));
|
||||
s->ref = 1;
|
||||
s->recycleBinEnumImpl.lpVtbl = &RecycleBinGenericEnumVtbl;
|
||||
|
||||
*pprbel = &s->recycleBinEnumImpl;
|
||||
return IRecycleBinEnumList_Reset(*pprbel);
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* PROJECT: Recycle bin management
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Enumerates contents of all recycle bins
|
||||
* COPYRIGHT: Copyright 2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||
* Copyright 2024 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||
*/
|
||||
|
||||
#include "recyclebin_private.h"
|
||||
|
||||
class RecycleBinGenericEnum : public IRecycleBinEnumList
|
||||
{
|
||||
public:
|
||||
RecycleBinGenericEnum();
|
||||
virtual ~RecycleBinGenericEnum();
|
||||
|
||||
/* IUnknown methods */
|
||||
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override;
|
||||
STDMETHODIMP_(ULONG) AddRef() override;
|
||||
STDMETHODIMP_(ULONG) Release() override;
|
||||
|
||||
/* IRecycleBinEnumList methods */
|
||||
STDMETHODIMP Next(DWORD celt, IRecycleBinFile **rgelt, DWORD *pceltFetched) override;
|
||||
STDMETHODIMP Skip(DWORD celt) override;
|
||||
STDMETHODIMP Reset() override;
|
||||
|
||||
protected:
|
||||
LONG m_ref;
|
||||
IRecycleBinEnumList *m_current;
|
||||
DWORD m_dwLogicalDrives;
|
||||
SIZE_T m_skip;
|
||||
};
|
||||
|
||||
STDMETHODIMP
|
||||
RecycleBinGenericEnum::QueryInterface(REFIID riid, void **ppvObject)
|
||||
{
|
||||
TRACE("(%p, %s, %p)\n", this, debugstr_guid(&riid), ppvObject);
|
||||
|
||||
if (!ppvObject)
|
||||
return E_POINTER;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IRecycleBinEnumList))
|
||||
*ppvObject = static_cast<IRecycleBinEnumList *>(this);
|
||||
else
|
||||
{
|
||||
*ppvObject = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG)
|
||||
RecycleBinGenericEnum::AddRef()
|
||||
{
|
||||
ULONG refCount = InterlockedIncrement(&m_ref);
|
||||
TRACE("(%p)\n", this);
|
||||
return refCount;
|
||||
}
|
||||
|
||||
RecycleBinGenericEnum::~RecycleBinGenericEnum()
|
||||
{
|
||||
TRACE("(%p)\n", this);
|
||||
|
||||
if (m_current)
|
||||
m_current->Release();
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG)
|
||||
RecycleBinGenericEnum::Release()
|
||||
{
|
||||
TRACE("(%p)\n", this);
|
||||
|
||||
ULONG refCount = InterlockedDecrement(&m_ref);
|
||||
if (refCount == 0)
|
||||
delete this;
|
||||
return refCount;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
RecycleBinGenericEnum::Next(DWORD celt, IRecycleBinFile **rgelt, DWORD *pceltFetched)
|
||||
{
|
||||
TRACE("(%p, %u, %p, %p)\n", this, celt, rgelt, pceltFetched);
|
||||
|
||||
if (!rgelt)
|
||||
return E_POINTER;
|
||||
if (!pceltFetched && celt > 1)
|
||||
return E_INVALIDARG;
|
||||
|
||||
HRESULT hr;
|
||||
DWORD fetched = 0;
|
||||
while (TRUE)
|
||||
{
|
||||
/* Get enumerator implementation */
|
||||
if (!m_current && m_dwLogicalDrives)
|
||||
{
|
||||
for (DWORD i = 0; i < L'Z' - L'A' + 1; ++i)
|
||||
{
|
||||
if (m_dwLogicalDrives & (1 << i))
|
||||
{
|
||||
WCHAR szVolumeName[4];
|
||||
szVolumeName[0] = (WCHAR)(L'A' + i);
|
||||
szVolumeName[1] = L':';
|
||||
szVolumeName[2] = L'\\';
|
||||
szVolumeName[3] = UNICODE_NULL;
|
||||
if (GetDriveTypeW(szVolumeName) != DRIVE_FIXED)
|
||||
{
|
||||
m_dwLogicalDrives &= ~(1 << i);
|
||||
continue;
|
||||
}
|
||||
|
||||
IRecycleBin *prb;
|
||||
hr = GetDefaultRecycleBin(szVolumeName, &prb);
|
||||
if (!SUCCEEDED(hr))
|
||||
return hr;
|
||||
hr = prb->EnumObjects(&m_current);
|
||||
prb->Release();
|
||||
|
||||
if (!SUCCEEDED(hr))
|
||||
return hr;
|
||||
|
||||
m_dwLogicalDrives &= ~(1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_current)
|
||||
{
|
||||
/* Nothing more to enumerate */
|
||||
if (pceltFetched)
|
||||
*pceltFetched = fetched;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
/* Skip some elements */
|
||||
while (m_skip > 0)
|
||||
{
|
||||
IRecycleBinFile *rbf;
|
||||
hr = m_current->Next(1, &rbf, NULL);
|
||||
if (hr == S_OK)
|
||||
rbf->Release();
|
||||
else if (hr == S_FALSE)
|
||||
break;
|
||||
else if (!SUCCEEDED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (m_skip > 0)
|
||||
continue;
|
||||
|
||||
/* Fill area */
|
||||
DWORD newFetched;
|
||||
hr = m_current->Next(celt - fetched, &rgelt[fetched], &newFetched);
|
||||
if (SUCCEEDED(hr))
|
||||
fetched += newFetched;
|
||||
|
||||
if (hr == S_FALSE || newFetched == 0)
|
||||
{
|
||||
m_current->Release();
|
||||
m_current = NULL;
|
||||
}
|
||||
else if (!SUCCEEDED(hr))
|
||||
return hr;
|
||||
|
||||
if (fetched == celt)
|
||||
{
|
||||
if (pceltFetched)
|
||||
*pceltFetched = fetched;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Never go here */
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
STDMETHODIMP RecycleBinGenericEnum::Skip(DWORD celt)
|
||||
{
|
||||
TRACE("(%p, %u)\n", this, celt);
|
||||
m_skip += celt;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP RecycleBinGenericEnum::Reset()
|
||||
{
|
||||
TRACE("(%p)\n", this);
|
||||
|
||||
if (m_current)
|
||||
{
|
||||
m_current->Release();
|
||||
m_current = NULL;
|
||||
}
|
||||
m_skip = 0;
|
||||
m_dwLogicalDrives = ::GetLogicalDrives();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
RecycleBinGenericEnum::RecycleBinGenericEnum()
|
||||
: m_ref(1)
|
||||
, m_current(NULL)
|
||||
, m_dwLogicalDrives(0)
|
||||
, m_skip(0)
|
||||
{
|
||||
}
|
||||
|
||||
EXTERN_C
|
||||
HRESULT
|
||||
RecycleBinGenericEnum_Constructor(
|
||||
OUT IRecycleBinEnumList **pprbel)
|
||||
{
|
||||
RecycleBinGenericEnum *pThis = new RecycleBinGenericEnum();
|
||||
if (!pThis)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
*pprbel = static_cast<IRecycleBinEnumList *>(pThis);
|
||||
return (*pprbel)->Reset();
|
||||
}
|
|
@ -44,6 +44,7 @@ HRESULT RecycleBinGeneric_Constructor(OUT IUnknown **ppUnknown);
|
|||
|
||||
/* recyclebin_generic_enumerator.c */
|
||||
|
||||
EXTERN_C
|
||||
HRESULT RecycleBinGenericEnum_Constructor(OUT IRecycleBinEnumList **pprbel);
|
||||
|
||||
/* recyclebin_v5.c */
|
||||
|
|
Loading…
Reference in a new issue