[SHELL32] Implement Recycler Bin icons (#4221)

CORE-3938

Icon extraction from the recycle bin was not possible due to the partial absence of IExtractIcon interface support.
Adding it inside the RecycleBinFile's QueryInterface private implementation, and then calling it from CRecycleBin, now allows retrieving and displaying the files' icons.
This commit is contained in:
Jesús Sanz del Rey 2022-01-17 00:20:07 +01:00 committed by GitHub
parent 63cd5d54b8
commit 9c6f1958d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 9 deletions

View file

@ -62,14 +62,53 @@ static const columninfo RecycleBinColumns[] =
* Recycle Bin folder
*/
HRESULT CRecyclerExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut)
BOOL WINAPI CBSearchRecycleBin(IN PVOID Context, IN HANDLE hDeletedFile);
static PIDLRecycleStruct * _ILGetRecycleStruct(LPCITEMIDLIST pidl);
typedef struct _SEARCH_CONTEXT
{
PIDLRecycleStruct *pFileDetails;
HANDLE hDeletedFile;
BOOL bFound;
} SEARCH_CONTEXT, *PSEARCH_CONTEXT;
HRESULT CRecyclerExtractIcon_CreateInstance(
LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut)
{
PIDLRecycleStruct *pFileDetails = _ILGetRecycleStruct(pidl);
if (pFileDetails == NULL)
goto fallback;
// Try to obtain the file
SEARCH_CONTEXT Context;
Context.pFileDetails = pFileDetails;
Context.bFound = FALSE;
EnumerateRecycleBinW(NULL, CBSearchRecycleBin, &Context);
if (Context.bFound)
{
// This should be executed any time, if not, there are some errors in the implementation
IRecycleBinFile* pRecycleFile = (IRecycleBinFile*)Context.hDeletedFile;
// Query the interface from the private interface
HRESULT hr = pRecycleFile->QueryInterface(riid, ppvOut);
// Close the file handle as we don't need it anymore
CloseRecycleBinHandle(Context.hDeletedFile);
return hr;
}
fallback:
// In case the search fails we use a default icon
ERR("Recycler could not retrieve the icon, this shouldn't happen\n");
CComPtr<IDefaultExtractIconInit> initIcon;
HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
/* FIXME: This is completely unimplemented */
initIcon->SetNormalIcon(swShell32Name, 0);
return initIcon->QueryInterface(riid, ppvOut);
@ -116,13 +155,6 @@ class CRecycleBinItemContextMenu :
END_COM_MAP()
};
typedef struct
{
PIDLRecycleStruct *pFileDetails;
HANDLE hDeletedFile;
BOOL bFound;
} SEARCH_CONTEXT, *PSEARCH_CONTEXT;
BOOL WINAPI CBSearchRecycleBin(IN PVOID Context, IN HANDLE hDeletedFile)
{
PSEARCH_CONTEXT pContext = (PSEARCH_CONTEXT)Context;

View file

@ -5,6 +5,8 @@
#define COBJMACROS
#include <shlobj.h>
#include "recyclebin.h"
#include "recyclebin_v5.h"

View file

@ -17,6 +17,11 @@ struct RecycleBin5File
WCHAR FullName[ANY_SIZE];
};
static HRESULT STDMETHODCALLTYPE
RecycleBin5File_RecycleBinFile_GetAttributes(
IN IRecycleBinFile *This,
OUT DWORD *pAttributes);
static HRESULT STDMETHODCALLTYPE
RecycleBin5File_RecycleBinFile_QueryInterface(
IN IRecycleBinFile *This,
@ -34,6 +39,14 @@ RecycleBin5File_RecycleBinFile_QueryInterface(
*ppvObject = &s->recycleBinFileImpl;
else if (IsEqualIID(riid, &IID_IRecycleBinFile))
*ppvObject = &s->recycleBinFileImpl;
else if (IsEqualIID(riid, &IID_IExtractIconA) || IsEqualIID(riid, &IID_IExtractIconW))
{
DWORD dwAttributes;
if (RecycleBin5File_RecycleBinFile_GetAttributes(This, &dwAttributes) == S_OK)
return SHCreateFileExtractIconW(s->FullName, dwAttributes, riid, ppvObject);
else
return S_FALSE;
}
else
{
*ppvObject = NULL;