mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-26 19:33:31 +00:00
[SHELL32] RecycleBinGeneric: Make it C++ (#7169)
Modernize code. JIRA issue: CORE-19595 Rewrite RecycleBinGeneric in C++.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 ([email protected])
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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 ([email protected])
|
||||
* Copyright 2024 Katayama Hirofumi MZ ([email protected])
|
||||
*/
|
||||
|
||||
#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<IRecycleBin *>(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<IRecycleBin *>(pThis);
|
||||
return S_OK;
|
||||
}
|
||||
@@ -40,6 +40,7 @@ typedef struct _INFO2_HEADER
|
||||
|
||||
/* recyclebin_generic.c */
|
||||
|
||||
EXTERN_C
|
||||
HRESULT RecycleBinGeneric_Constructor(OUT IUnknown **ppUnknown);
|
||||
|
||||
/* recyclebin_generic_enumerator.c */
|
||||
|
||||
Reference in New Issue
Block a user