From 6910fa624fe1fe5faa830bd70f7f9f7ba53909fe Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Wed, 24 Jul 2024 12:16:37 +0900 Subject: [PATCH] [SHELL32] RecycleBinGeneric: Make it C++ (#7169) Modernize code. JIRA issue: CORE-19595 Rewrite RecycleBinGeneric in C++. --- .../shell32/shellrecyclebin/CMakeLists.txt | 2 +- .../shellrecyclebin/recyclebin_generic.c | 214 ------------------ .../shellrecyclebin/recyclebin_generic.cpp | 177 +++++++++++++++ .../shellrecyclebin/recyclebin_private.h | 1 + 4 files changed, 179 insertions(+), 215 deletions(-) delete mode 100644 dll/win32/shell32/shellrecyclebin/recyclebin_generic.c create mode 100644 dll/win32/shell32/shellrecyclebin/recyclebin_generic.cpp diff --git a/dll/win32/shell32/shellrecyclebin/CMakeLists.txt b/dll/win32/shell32/shellrecyclebin/CMakeLists.txt index 1ca6eedc6c8..5ff948c8a95 100644 --- a/dll/win32/shell32/shellrecyclebin/CMakeLists.txt +++ b/dll/win32/shell32/shellrecyclebin/CMakeLists.txt @@ -6,7 +6,7 @@ add_definitions( list(APPEND SOURCE recyclebin.c - recyclebin_generic.c + recyclebin_generic.cpp recyclebin_generic_enumerator.cpp recyclebin_v5.c recyclebin_v5_enumerator.c diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_generic.c b/dll/win32/shell32/shellrecyclebin/recyclebin_generic.c deleted file mode 100644 index 879951e2838..00000000000 --- a/dll/win32/shell32/shellrecyclebin/recyclebin_generic.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * PROJECT: Recycle bin management - * LICENSE: GPL v2 - See COPYING in the top level directory - * FILE: lib/recyclebin/recyclebin_generic.c - * PURPOSE: Deals with a system-wide recycle bin - * PROGRAMMERS: Copyright 2007 Hervé Poussineau (hpoussin@reactos.org) - */ - -#include "recyclebin_private.h" - -struct RecycleBinGeneric -{ - ULONG ref; - IRecycleBin recycleBinImpl; -}; - -static HRESULT STDMETHODCALLTYPE -RecycleBinGeneric_RecycleBin_QueryInterface( - IRecycleBin *This, - REFIID riid, - void **ppvObject) -{ - struct RecycleBinGeneric *s = CONTAINING_RECORD(This, struct RecycleBinGeneric, recycleBinImpl); - - TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObject); - - if (!ppvObject) - return E_POINTER; - - if (IsEqualIID(riid, &IID_IUnknown)) - *ppvObject = &s->recycleBinImpl; - else if (IsEqualIID(riid, &IID_IRecycleBin)) - *ppvObject = &s->recycleBinImpl; - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } - - IUnknown_AddRef(This); - return S_OK; -} - -static ULONG STDMETHODCALLTYPE -RecycleBinGeneric_RecycleBin_AddRef( - IRecycleBin *This) -{ - struct RecycleBinGeneric *s = CONTAINING_RECORD(This, struct RecycleBinGeneric, recycleBinImpl); - ULONG refCount = InterlockedIncrement((PLONG)&s->ref); - TRACE("(%p)\n", This); - return refCount; -} - -static VOID -RecycleBinGeneric_Destructor( - struct RecycleBinGeneric *s) -{ - TRACE("(%p)\n", s); - - CoTaskMemFree(s); -} - -static ULONG STDMETHODCALLTYPE -RecycleBinGeneric_RecycleBin_Release( - IRecycleBin *This) -{ - struct RecycleBinGeneric *s = CONTAINING_RECORD(This, struct RecycleBinGeneric, recycleBinImpl); - ULONG refCount; - - TRACE("(%p)\n", This); - - refCount = InterlockedDecrement((PLONG)&s->ref); - - if (refCount == 0) - RecycleBinGeneric_Destructor(s); - - return refCount; -} - -static HRESULT STDMETHODCALLTYPE -RecycleBinGeneric_RecycleBin_DeleteFile( - IN IRecycleBin *This, - IN LPCWSTR szFileName) -{ - IRecycleBin *prb; - LPWSTR szFullName = NULL; - DWORD dwBufferLength = 0; - DWORD len; - WCHAR szVolume[MAX_PATH]; - HRESULT hr; - - TRACE("(%p, %s)\n", This, debugstr_w(szFileName)); - - /* Get full file name */ - while (TRUE) - { - len = GetFullPathNameW(szFileName, dwBufferLength, szFullName, NULL); - if (len == 0) - { - if (szFullName) - CoTaskMemFree(szFullName); - return HRESULT_FROM_WIN32(GetLastError()); - } - else if (len < dwBufferLength) - break; - if (szFullName) - CoTaskMemFree(szFullName); - dwBufferLength = len; - szFullName = CoTaskMemAlloc(dwBufferLength * sizeof(WCHAR)); - if (!szFullName) - return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); - } - - /* Get associated volume path */ -#ifndef __REACTOS__ - if (!GetVolumePathNameW(szFullName, szVolume, MAX_PATH)) - { - CoTaskMemFree(szFullName); - return HRESULT_FROM_WIN32(GetLastError()); - } -#else - swprintf(szVolume, L"%c:\\", szFullName[0]); -#endif - - /* Skip namespace (if any) */ - if (szVolume[0] == '\\' - && szVolume[1] == '\\' - && (szVolume[2] == '.' || szVolume[2] == '?') - && szVolume[3] == '\\') - { - MoveMemory(szVolume, &szVolume[4], (MAX_PATH - 4) * sizeof(WCHAR)); - } - - hr = GetDefaultRecycleBin(szVolume, &prb); - if (!SUCCEEDED(hr)) - { - CoTaskMemFree(szFullName); - return hr; - } - - hr = IRecycleBin_DeleteFile(prb, szFullName); - CoTaskMemFree(szFullName); - IRecycleBin_Release(prb); - return hr; -} - -static HRESULT STDMETHODCALLTYPE -RecycleBinGeneric_RecycleBin_EmptyRecycleBin( - IN IRecycleBin *This) -{ - WCHAR szVolumeName[MAX_PATH]; - DWORD dwLogicalDrives, i; - IRecycleBin *prb; - HRESULT hr; - - TRACE("(%p)\n", This); - - dwLogicalDrives = GetLogicalDrives(); - if (dwLogicalDrives == 0) - return HRESULT_FROM_WIN32(GetLastError()); - - for (i = 0; i < 26; i++) - { - if (!(dwLogicalDrives & (1 << i))) - continue; - swprintf(szVolumeName, L"%c:\\", 'A' + i); - if (GetDriveTypeW(szVolumeName) != DRIVE_FIXED) - continue; - - hr = GetDefaultRecycleBin(szVolumeName, &prb); - if (!SUCCEEDED(hr)) - return hr; - - hr = IRecycleBin_EmptyRecycleBin(prb); - IRecycleBin_Release(prb); - } - - return S_OK; -} - -static HRESULT STDMETHODCALLTYPE -RecycleBinGeneric_RecycleBin_EnumObjects( - IN IRecycleBin *This, - OUT IRecycleBinEnumList **ppEnumList) -{ - TRACE("(%p, %p)\n", This, ppEnumList); - return RecycleBinGenericEnum_Constructor(ppEnumList); -} - -CONST_VTBL struct IRecycleBinVtbl RecycleBinGenericVtbl = -{ - RecycleBinGeneric_RecycleBin_QueryInterface, - RecycleBinGeneric_RecycleBin_AddRef, - RecycleBinGeneric_RecycleBin_Release, - RecycleBinGeneric_RecycleBin_DeleteFile, - RecycleBinGeneric_RecycleBin_EmptyRecycleBin, - RecycleBinGeneric_RecycleBin_EnumObjects, -}; - -HRESULT RecycleBinGeneric_Constructor(OUT IUnknown **ppUnknown) -{ - /* This RecycleBin implementation was introduced to be able to manage all - * drives at once, and instanciate the 'real' implementations when needed */ - struct RecycleBinGeneric *s; - - s = CoTaskMemAlloc(sizeof(struct RecycleBinGeneric)); - if (!s) - return E_OUTOFMEMORY; - s->ref = 1; - s->recycleBinImpl.lpVtbl = &RecycleBinGenericVtbl; - - *ppUnknown = (IUnknown *)&s->recycleBinImpl; - return S_OK; -} diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_generic.cpp b/dll/win32/shell32/shellrecyclebin/recyclebin_generic.cpp new file mode 100644 index 00000000000..c9a010e12b0 --- /dev/null +++ b/dll/win32/shell32/shellrecyclebin/recyclebin_generic.cpp @@ -0,0 +1,177 @@ +/* + * PROJECT: Recycle bin management + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Deals with a system-wide recycle bin + * COPYRIGHT: Copyright 2007 HervĂ© Poussineau (hpoussin@reactos.org) + * Copyright 2024 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + */ + +#include "recyclebin_private.h" + +class RecycleBinGeneric : public IRecycleBin +{ +public: + RecycleBinGeneric(); + virtual ~RecycleBinGeneric(); + + /* IUnknown methods */ + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + /* IRecycleBin methods */ + STDMETHODIMP DeleteFile(LPCWSTR szFileName) override; + STDMETHODIMP EmptyRecycleBin() override; + STDMETHODIMP EnumObjects(IRecycleBinEnumList **ppEnumList) override; + +protected: + LONG m_ref; +}; + +STDMETHODIMP RecycleBinGeneric::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_IRecycleBin)) + *ppvObject = static_cast(this); + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; +} + +STDMETHODIMP_(ULONG) RecycleBinGeneric::AddRef() +{ + ULONG refCount = InterlockedIncrement(&m_ref); + TRACE("(%p)\n", this); + return refCount; +} + +RecycleBinGeneric::~RecycleBinGeneric() +{ + TRACE("(%p)\n", this); +} + +STDMETHODIMP_(ULONG) RecycleBinGeneric::Release() +{ + TRACE("(%p)\n", this); + + ULONG refCount = InterlockedDecrement(&m_ref); + if (refCount == 0) + delete this; + return refCount; +} + +STDMETHODIMP RecycleBinGeneric::DeleteFile(LPCWSTR szFileName) +{ + TRACE("(%p, %s)\n", this, debugstr_w(szFileName)); + + /* Get full file name */ + LPWSTR szFullName = NULL; + DWORD dwBufferLength = 0; + while (TRUE) + { + DWORD len = GetFullPathNameW(szFileName, dwBufferLength, szFullName, NULL); + if (len == 0) + { + if (szFullName) + CoTaskMemFree(szFullName); + return HRESULT_FROM_WIN32(GetLastError()); + } + else if (len < dwBufferLength) + break; + if (szFullName) + CoTaskMemFree(szFullName); + dwBufferLength = len; + szFullName = (LPWSTR)CoTaskMemAlloc(dwBufferLength * sizeof(WCHAR)); + if (!szFullName) + return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + } + + /* Get associated volume path */ + WCHAR szVolume[MAX_PATH]; + swprintf(szVolume, L"%c:\\", szFullName[0]); + + /* Skip namespace (if any): "\\.\" or "\\?\" */ + if (szVolume[0] == '\\' && + szVolume[1] == '\\' && + (szVolume[2] == '.' || szVolume[2] == '?') && + szVolume[3] == '\\') + { + MoveMemory(szVolume, &szVolume[4], (_countof(szVolume) - 4) * sizeof(WCHAR)); + } + + IRecycleBin *prb; + HRESULT hr = GetDefaultRecycleBin(szVolume, &prb); + if (!SUCCEEDED(hr)) + { + CoTaskMemFree(szFullName); + return hr; + } + + hr = prb->DeleteFile(szFullName); + CoTaskMemFree(szFullName); + prb->Release(); + return hr; +} + +STDMETHODIMP RecycleBinGeneric::EmptyRecycleBin() +{ + TRACE("(%p)\n", this); + + DWORD dwLogicalDrives = GetLogicalDrives(); + if (dwLogicalDrives == 0) + return HRESULT_FROM_WIN32(GetLastError()); + + for (DWORD i = 0; i < L'Z' - L'A' + 1; i++) + { + if (!(dwLogicalDrives & (1 << i))) + continue; + + WCHAR szVolumeName[MAX_PATH]; + swprintf(szVolumeName, L"%c:\\", L'A' + i); + if (GetDriveTypeW(szVolumeName) != DRIVE_FIXED) + continue; + + IRecycleBin *prb; + HRESULT hr = GetDefaultRecycleBin(szVolumeName, &prb); + if (!SUCCEEDED(hr)) + return hr; + + hr = prb->EmptyRecycleBin(); + prb->Release(); + } + + return S_OK; +} + +STDMETHODIMP RecycleBinGeneric::EnumObjects(IRecycleBinEnumList **ppEnumList) +{ + TRACE("(%p, %p)\n", this, ppEnumList); + return RecycleBinGenericEnum_Constructor(ppEnumList); +} + +RecycleBinGeneric::RecycleBinGeneric() + : m_ref(1) +{ +} + +EXTERN_C +HRESULT RecycleBinGeneric_Constructor(OUT IUnknown **ppUnknown) +{ + /* This RecycleBin implementation was introduced to be able to manage all + * drives at once, and instanciate the 'real' implementations when needed */ + RecycleBinGeneric *pThis = new RecycleBinGeneric(); + if (!pThis) + return E_OUTOFMEMORY; + + *ppUnknown = static_cast(pThis); + return S_OK; +} diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_private.h b/dll/win32/shell32/shellrecyclebin/recyclebin_private.h index b4eb6c4a94a..aba8decdfd1 100644 --- a/dll/win32/shell32/shellrecyclebin/recyclebin_private.h +++ b/dll/win32/shell32/shellrecyclebin/recyclebin_private.h @@ -40,6 +40,7 @@ typedef struct _INFO2_HEADER /* recyclebin_generic.c */ +EXTERN_C HRESULT RecycleBinGeneric_Constructor(OUT IUnknown **ppUnknown); /* recyclebin_generic_enumerator.c */