diff --git a/dll/win32/shell32/folders/CRecycleBin.cpp b/dll/win32/shell32/folders/CRecycleBin.cpp index 48d285c9ac7..ee6c6d60754 100644 --- a/dll/win32/shell32/folders/CRecycleBin.cpp +++ b/dll/win32/shell32/folders/CRecycleBin.cpp @@ -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 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; diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_private.h b/dll/win32/shell32/shellrecyclebin/recyclebin_private.h index 9686bdfccee..6c90aa94728 100644 --- a/dll/win32/shell32/shellrecyclebin/recyclebin_private.h +++ b/dll/win32/shell32/shellrecyclebin/recyclebin_private.h @@ -5,6 +5,8 @@ #define COBJMACROS +#include + #include "recyclebin.h" #include "recyclebin_v5.h" diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_v5_enumerator.c b/dll/win32/shell32/shellrecyclebin/recyclebin_v5_enumerator.c index bbe4fa1e834..411c623b3a2 100644 --- a/dll/win32/shell32/shellrecyclebin/recyclebin_v5_enumerator.c +++ b/dll/win32/shell32/shellrecyclebin/recyclebin_v5_enumerator.c @@ -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;