https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bc8c7d185d059677c9fe1c112584e00181807d55

commit bc8c7d185d059677c9fe1c112584e00181807d55
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Sun Sep 8 22:08:15 2024 +0200
Commit:     GitHub <nore...@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);

Reply via email to