diff --git a/dll/win32/shell32/shellrecyclebin/CMakeLists.txt b/dll/win32/shell32/shellrecyclebin/CMakeLists.txt index 627d4ae013a..1ca6eedc6c8 100644 --- a/dll/win32/shell32/shellrecyclebin/CMakeLists.txt +++ b/dll/win32/shell32/shellrecyclebin/CMakeLists.txt @@ -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) diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin.h b/dll/win32/shell32/shellrecyclebin/recyclebin.h index a27d2f530bb..a48f49264cf 100644 --- a/dll/win32/shell32/shellrecyclebin/recyclebin.h +++ b/dll/win32/shell32/shellrecyclebin/recyclebin.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; diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_generic_enumerator.c b/dll/win32/shell32/shellrecyclebin/recyclebin_generic_enumerator.c deleted file mode 100644 index 30b354c6b96..00000000000 --- a/dll/win32/shell32/shellrecyclebin/recyclebin_generic_enumerator.c +++ /dev/null @@ -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); -} diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_generic_enumerator.cpp b/dll/win32/shell32/shellrecyclebin/recyclebin_generic_enumerator.cpp new file mode 100644 index 00000000000..4cf3cde0c50 --- /dev/null +++ b/dll/win32/shell32/shellrecyclebin/recyclebin_generic_enumerator.cpp @@ -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(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(pThis); + return (*pprbel)->Reset(); +} diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_private.h b/dll/win32/shell32/shellrecyclebin/recyclebin_private.h index 6c90aa94728..b4eb6c4a94a 100644 --- a/dll/win32/shell32/shellrecyclebin/recyclebin_private.h +++ b/dll/win32/shell32/shellrecyclebin/recyclebin_private.h @@ -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 */