https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f283a3f9ae16eb047d602…
commit f283a3f9ae16eb047d60272186fcb911c79dc266
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Mon Nov 13 16:31:37 2023 +0100
Commit: GitHub <noreply(a)github.com>
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;
}