https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bc8c7d185d059677c9fe1…
commit bc8c7d185d059677c9fe1c112584e00181807d55
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Sun Sep 8 22:08:15 2024 +0200
Commit: GitHub <noreply(a)github.com>
CommitDate: Sun Sep 8 22:08:15 2024 +0200
[SHELL32] Fix CRecycleBin crash caused by PR #7173 (#7330)
PR #7173 (22b913928f4a1d13120b0ec7a1c6889d37ec0e3a) fails to initialize the
DELETED_FILE_RECORD struct when constructing a RecycleBin5File instance. This causes
_ILCreateRecycleItem to create PIDLs without filenames and the CRecycleBin IShellFolder
does not expect this to happen.
Also fixes incorrect usage of SHFileOperationW when restoring deleted files. The
previous code might have worked by chance in the past if the string just happened to be
double-null terminated as required by this API!
---
.../shell32/shellrecyclebin/recyclebin_v5.cpp | 45 ++++++++++++++++++----
.../shellrecyclebin/recyclebin_v5_enumerator.cpp | 1 +
2 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_v5.cpp
b/dll/win32/shell32/shellrecyclebin/recyclebin_v5.cpp
index a98e56861bb..c7009f94d9d 100644
--- a/dll/win32/shell32/shellrecyclebin/recyclebin_v5.cpp
+++ b/dll/win32/shell32/shellrecyclebin/recyclebin_v5.cpp
@@ -11,6 +11,40 @@
#include <shlwapi.h>
#include "sddl.h"
+EXTERN_C HRESULT WINAPI SHUpdateRecycleBinIcon(void);
+
+class CZZWStr
+{
+ LPWSTR m_sz;
+
+public:
+ ~CZZWStr() { SHFree(m_sz); }
+ CZZWStr() : m_sz(NULL) {}
+ CZZWStr(const CZZWStr&) = delete;
+ CZZWStr& operator=(const CZZWStr&) = delete;
+
+ bool Initialize(LPCWSTR Str)
+ {
+ SIZE_T cch = wcslen(Str) + 1;
+ m_sz = (LPWSTR)SHAlloc((cch + 1) * sizeof(*Str));
+ if (!m_sz)
+ return false;
+ CopyMemory(m_sz, Str, cch * sizeof(*Str));
+ m_sz[cch] = UNICODE_NULL; // Double-null terminate
+ return true;
+ }
+ inline LPWSTR c_str() { return m_sz; }
+};
+
+static int SHELL_SingleFileOperation(HWND hWnd, UINT Op, LPCWSTR pszFrom, LPCWSTR pszTo,
FILEOP_FLAGS Flags)
+{
+ CZZWStr szzFrom, szzTo;
+ if (!szzFrom.Initialize(pszFrom) || !szzTo.Initialize(pszTo))
+ return ERROR_OUTOFMEMORY; // Note: Not one of the DE errors but also not in the
DE range
+ SHFILEOPSTRUCTW fos = { hWnd, Op, szzFrom.c_str(), szzTo.c_str(), Flags };
+ return SHFileOperationW(&fos);
+}
+
static BOOL
IntDeleteRecursive(
IN LPCWSTR FullName)
@@ -465,7 +499,6 @@ STDMETHODIMP RecycleBin5::Restore(
PINFO2_HEADER pHeader;
DELETED_FILE_RECORD *pRecord, *pLast;
DWORD dwEntries, i;
- SHFILEOPSTRUCTW op;
int res;
TRACE("(%p, %s, %p)\n", this, debugstr_w(pDeletedFileName), pDeletedFile);
@@ -490,13 +523,7 @@ STDMETHODIMP RecycleBin5::Restore(
{
if (pRecord->dwRecordUniqueId == pDeletedFile->dwRecordUniqueId)
{
- /* Restore file */
- ZeroMemory(&op, sizeof(op));
- op.wFunc = FO_MOVE;
- op.pFrom = pDeletedFileName;
- op.pTo = pDeletedFile->FileNameW;
-
- res = SHFileOperationW(&op);
+ res = SHELL_SingleFileOperation(NULL, FO_MOVE, pDeletedFileName,
pDeletedFile->FileNameW, 0);
if (res)
{
ERR("SHFileOperationW failed with 0x%x\n", res);
@@ -517,6 +544,8 @@ STDMETHODIMP RecycleBin5::Restore(
m_hInfoMapped = CreateFileMappingW(m_hInfo, NULL, PAGE_READWRITE |
SEC_COMMIT, 0, 0, NULL);
if (!m_hInfoMapped)
return HRESULT_FROM_WIN32(GetLastError());
+ if (dwEntries == 1)
+ SHUpdateRecycleBinIcon(); // Full --> Empty
return S_OK;
}
pRecord++;
diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_v5_enumerator.cpp
b/dll/win32/shell32/shellrecyclebin/recyclebin_v5_enumerator.cpp
index 1f7855415d8..ff2593fe84d 100644
--- a/dll/win32/shell32/shellrecyclebin/recyclebin_v5_enumerator.cpp
+++ b/dll/win32/shell32/shellrecyclebin/recyclebin_v5_enumerator.cpp
@@ -257,6 +257,7 @@ RecycleBin5File::Init(
{
m_recycleBin = prb;
m_recycleBin->AddRef();
+ m_deletedFile = *pDeletedFile;
WCHAR szUniqueId[32];
StringCchPrintfW(szUniqueId, _countof(szUniqueId), L"%lu",
pDeletedFile->dwRecordUniqueId);