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

commit f283a3f9ae16eb047d60272186fcb911c79dc266
Author:     Whindmar Saksit <[email protected]>
AuthorDate: Mon Nov 13 16:31:37 2023 +0100
Commit:     GitHub <[email protected]>
CommitDate: Mon Nov 13 16:31:37 2023 +0100

    [SHELL32][SHELLEXT] IEnumIDList::Next must handle pceltFetched and memory 
errors correctly (#5820)
    
    - pceltFetched can be NULL if the caller is not requesting multiple items.
    - All entries returned in rgelt must be valid, they cannot be NULL.
---
 dll/shellext/fontext/CEnumFonts.cpp       | 21 ++++++++++++++++-----
 dll/shellext/netshell/enumlist.cpp        |  8 ++++++++
 dll/shellext/zipfldr/CEnumZipContents.cpp | 24 ++++++++++++------------
 dll/win32/shell32/CEnumIDListBase.cpp     |  6 ++++++
 4 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/dll/shellext/fontext/CEnumFonts.cpp 
b/dll/shellext/fontext/CEnumFonts.cpp
index 3897a73debd..957e816d322 100644
--- a/dll/shellext/fontext/CEnumFonts.cpp
+++ b/dll/shellext/fontext/CEnumFonts.cpp
@@ -36,9 +36,10 @@ public:
     // *** IEnumIDList methods ***
     STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
     {
-        if (!pceltFetched || !rgelt)
+        if (!rgelt || (!pceltFetched && celt != 1))
             return E_POINTER;
 
+        HRESULT hr = S_OK;
         ULONG Fetched = 0;
 
         while (celt)
@@ -48,15 +49,25 @@ public:
             if (m_Index < g_FontCache->Size())
             {
                 CStringW Name = g_FontCache->Name(m_Index);
-                rgelt[Fetched] = _ILCreate(Name, m_Index);
-
+                LPITEMIDLIST item = _ILCreate(Name, m_Index);
+                if (!item)
+                {
+                    hr = Fetched ? S_FALSE : E_OUTOFMEMORY;
+                    break;
+                }
+                rgelt[Fetched] = item;
                 m_Index++;
                 Fetched++;
             }
+            else
+            {
+                hr = S_FALSE;
+            }
         }
 
-        *pceltFetched = Fetched;
-        return Fetched ? S_OK : S_FALSE;
+        if (pceltFetched)
+            *pceltFetched = Fetched;
+        return hr;
     }
     STDMETHODIMP Skip(ULONG celt)
     {
diff --git a/dll/shellext/netshell/enumlist.cpp 
b/dll/shellext/netshell/enumlist.cpp
index a95eab776d8..9369663f708 100644
--- a/dll/shellext/netshell/enumlist.cpp
+++ b/dll/shellext/netshell/enumlist.cpp
@@ -277,9 +277,17 @@ CEnumIDList::Next(
     for (i = 0; i < celt; i++)
     {
         if (!m_pCurrent)
+        {
+            hr = S_FALSE;
             break;
+        }
 
         temp = ILClone(m_pCurrent->pidl);
+        if (!temp)
+        {
+            hr = i ? S_FALSE : E_OUTOFMEMORY;
+            break;
+        }
         rgelt[i] = temp;
         m_pCurrent = m_pCurrent->pNext;
     }
diff --git a/dll/shellext/zipfldr/CEnumZipContents.cpp 
b/dll/shellext/zipfldr/CEnumZipContents.cpp
index 372e21ba772..a3f5bcbf79c 100644
--- a/dll/shellext/zipfldr/CEnumZipContents.cpp
+++ b/dll/shellext/zipfldr/CEnumZipContents.cpp
@@ -34,25 +34,25 @@ public:
     // *** IEnumIDList methods ***
     STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
     {
-        if (!pceltFetched || !rgelt)
+        if (!rgelt || (!pceltFetched && celt != 1))
             return E_POINTER;
 
-        *pceltFetched = 0;
-
-        if (celt != 1)
-            return E_FAIL;
-
+        LPITEMIDLIST item;
         CStringW name;
         bool dir;
         unz_file_info64 info;
-        if (mEnumerator.next_unique(m_Prefix, name, dir, info))
+        for (ULONG i = 0; i < celt; ++i)
         {
-            *pceltFetched = 1;
-            *rgelt = _ILCreate(dir ? ZIP_PIDL_DIRECTORY : ZIP_PIDL_FILE, name, 
info);
-            return S_OK;
+            if (pceltFetched)
+                *pceltFetched = i;
+            if (!mEnumerator.next_unique(m_Prefix, name, dir, info))
+                return S_FALSE;
+            item = _ILCreate(dir ? ZIP_PIDL_DIRECTORY : ZIP_PIDL_FILE, name, 
info);
+            if (!item)
+                return i ? S_FALSE : E_OUTOFMEMORY;
+            rgelt[i] = item;
         }
-
-        return S_FALSE;
+        return S_OK;
     }
     STDMETHODIMP Skip(ULONG celt)
     {
diff --git a/dll/win32/shell32/CEnumIDListBase.cpp 
b/dll/win32/shell32/CEnumIDListBase.cpp
index 59633418c3d..47adf6e2ea8 100644
--- a/dll/win32/shell32/CEnumIDListBase.cpp
+++ b/dll/win32/shell32/CEnumIDListBase.cpp
@@ -172,9 +172,15 @@ HRESULT WINAPI CEnumIDListBase::Next(
 
     for(i = 0; i < celt; i++)
     { if(!mpCurrent)
+      { hr = S_FALSE;
         break;
+      }
 
       temp = ILClone(mpCurrent->pidl);
+      if (!temp)
+      { hr = i ? S_FALSE : E_OUTOFMEMORY;
+        break;
+      }
       rgelt[i] = temp;
       mpCurrent = mpCurrent->pNext;
     }

Reply via email to