[NTOBJSHEX]

* Fix leak of the PIDL and PIDL Manager from the shell folder destructors.
* Switch PIDL Manager to a lazy enumeration so it won't lookup the folder contents unless/until they are needed.

svn path=/trunk/; revision=66745
This commit is contained in:
David Quintana 2015-03-16 20:47:05 +00:00
parent 287b968fc1
commit be7e5a84eb
2 changed files with 112 additions and 17 deletions

View file

@ -177,6 +177,15 @@ public:
HRESULT Initialize(PWSTR ntPath)
{
m_ntPath = ntPath;
m_hDpa = NULL;
return S_OK;
}
HRESULT Enumerate()
{
if (m_hDpa)
return S_OK;
m_hDpa = DPA_Create(10);
@ -196,7 +205,12 @@ public:
if (!m_hDpa)
{
return E_FAIL;
hr = Enumerate();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (!m_hDpa)
return E_FAIL;
}
NtPidlEntry * info = (NtPidlEntry *) pcidl;
@ -234,9 +248,16 @@ public:
HRESULT FindByName(LPCWSTR strParsingName, NtPidlEntry ** pinfo)
{
HRESULT hr;
if (!m_hDpa)
{
return E_FAIL;
hr = Enumerate();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (!m_hDpa)
return E_FAIL;
}
TRACE("Searching for '%S' in a list of %d items\n", strParsingName, m_hDpaCount);
@ -263,6 +284,18 @@ public:
HRESULT GetPidl(UINT index, NtPidlEntry ** pEntry)
{
HRESULT hr;
if (!m_hDpa)
{
hr = Enumerate();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (!m_hDpa)
return E_FAIL;
}
*pEntry = NULL;
NtPidlEntry * entry = (NtPidlEntry *) DPA_GetPtr(m_hDpa, index);
@ -277,11 +310,22 @@ public:
HRESULT GetCount(UINT * count)
{
HRESULT hr;
if (!m_hDpa)
{
hr = Enumerate();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (!m_hDpa)
return E_FAIL;
}
*count = m_hDpaCount;
return S_OK;
}
static LPITEMIDLIST CreatePidlFromItem(NtPidlEntry * entry)
{
LPITEMIDLIST idl = (LPITEMIDLIST) CoTaskMemAlloc(entry->cb + 2);
@ -292,7 +336,7 @@ public:
return idl;
}
HRESULT CompareIDs(LPARAM lParam, NtPidlEntry * first, NtPidlEntry * second)
static HRESULT CompareIDs(LPARAM lParam, NtPidlEntry * first, NtPidlEntry * second)
{
if ((lParam & 0xFFFF0000) == SHCIDS_ALLFIELDS)
{
@ -387,7 +431,7 @@ public:
return E_INVALIDARG;
}
HRESULT CompareIDs(LPARAM lParam, NtPidlEntry * first, LPCITEMIDLIST pcidl)
static HRESULT CompareIDs(LPARAM lParam, NtPidlEntry * first, LPCITEMIDLIST pcidl)
{
LPCITEMIDLIST p = pcidl;
NtPidlEntry * second = (NtPidlEntry*) &(p->mkid);
@ -397,7 +441,7 @@ public:
return CompareIDs(lParam, first, second);
}
HRESULT CompareIDs(LPARAM lParam, LPCITEMIDLIST pcidl1, LPCITEMIDLIST pcidl2)
static HRESULT CompareIDs(LPARAM lParam, LPCITEMIDLIST pcidl1, LPCITEMIDLIST pcidl2)
{
LPCITEMIDLIST p = pcidl1;
NtPidlEntry * first = (NtPidlEntry*) &(p->mkid);
@ -407,7 +451,7 @@ public:
return CompareIDs(lParam, first, pcidl2);
}
ULONG ConvertAttributes(NtPidlEntry * entry, PULONG inMask)
static ULONG ConvertAttributes(NtPidlEntry * entry, PULONG inMask)
{
ULONG mask = inMask ? *inMask : 0xFFFFFFFF;
ULONG flags = SFGAO_HASPROPSHEET | SFGAO_CANLINK;
@ -564,7 +608,10 @@ CNtObjectFolder::CNtObjectFolder() :
CNtObjectFolder::~CNtObjectFolder()
{
TRACE("Destroying CNtObjectFolder %p\n", this);
if (m_shellPidl)
ILFree(m_shellPidl);
if (m_PidlManager)
delete m_PidlManager;
}
// IShellFolder

View file

@ -164,6 +164,15 @@ public:
{
m_ntPath = ntPath;
m_hRoot = hRoot;
m_hDpa = NULL;
return S_OK;
}
HRESULT Enumerate()
{
if (m_hDpa)
return S_OK;
m_hDpa = DPA_Create(10);
@ -182,7 +191,6 @@ public:
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
return S_OK;
}
@ -192,7 +200,12 @@ public:
if (!m_hDpa)
{
return E_FAIL;
hr = Enumerate();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (!m_hDpa)
return E_FAIL;
}
RegPidlEntry * info = (RegPidlEntry *) pcidl;
@ -230,11 +243,19 @@ public:
HRESULT FindByName(LPCWSTR strParsingName, RegPidlEntry ** pinfo)
{
HRESULT hr;
if (!m_hDpa)
{
return E_FAIL;
hr = Enumerate();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (!m_hDpa)
return E_FAIL;
}
TRACE("Searching for '%S' in a list of %d items\n", strParsingName, m_hDpaCount);
for (int i = 0; i < (int) m_hDpaCount; i++)
@ -259,6 +280,18 @@ public:
HRESULT GetPidl(UINT index, RegPidlEntry ** pEntry)
{
HRESULT hr;
if (!m_hDpa)
{
hr = Enumerate();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (!m_hDpa)
return E_FAIL;
}
*pEntry = NULL;
RegPidlEntry * entry = (RegPidlEntry *) DPA_GetPtr(m_hDpa, index);
@ -273,6 +306,18 @@ public:
HRESULT GetCount(UINT * count)
{
HRESULT hr;
if (!m_hDpa)
{
hr = Enumerate();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (!m_hDpa)
return E_FAIL;
}
*count = m_hDpaCount;
return S_OK;
}
@ -288,7 +333,7 @@ public:
return idl;
}
HRESULT CompareIDs(LPARAM lParam, RegPidlEntry * first, RegPidlEntry * second)
static HRESULT CompareIDs(LPARAM lParam, RegPidlEntry * first, RegPidlEntry * second)
{
if ((lParam & 0xFFFF0000) == SHCIDS_ALLFIELDS)
{
@ -373,7 +418,7 @@ public:
return E_INVALIDARG;
}
HRESULT CompareIDs(LPARAM lParam, RegPidlEntry * first, LPCITEMIDLIST pcidl)
static HRESULT CompareIDs(LPARAM lParam, RegPidlEntry * first, LPCITEMIDLIST pcidl)
{
LPCITEMIDLIST p = pcidl;
RegPidlEntry * second = (RegPidlEntry*) &(p->mkid);
@ -383,7 +428,7 @@ public:
return CompareIDs(lParam, first, second);
}
HRESULT CompareIDs(LPARAM lParam, LPCITEMIDLIST pcidl1, LPCITEMIDLIST pcidl2)
static HRESULT CompareIDs(LPARAM lParam, LPCITEMIDLIST pcidl1, LPCITEMIDLIST pcidl2)
{
LPCITEMIDLIST p = pcidl1;
RegPidlEntry * first = (RegPidlEntry*) &(p->mkid);
@ -393,7 +438,7 @@ public:
return CompareIDs(lParam, first, pcidl2);
}
ULONG ConvertAttributes(RegPidlEntry * entry, PULONG inMask)
static ULONG ConvertAttributes(RegPidlEntry * entry, PULONG inMask)
{
ULONG mask = inMask ? *inMask : 0xFFFFFFFF;
ULONG flags = 0;
@ -416,7 +461,7 @@ public:
(entry->entryType == REG_ENTRY_ROOT);
}
HRESULT FormatValueData(DWORD contentType, PVOID td, DWORD contentsLength, PCWSTR * strContents)
static HRESULT FormatValueData(DWORD contentType, PVOID td, DWORD contentsLength, PCWSTR * strContents)
{
switch (contentType)
{
@ -647,7 +692,10 @@ CRegistryFolder::CRegistryFolder() :
CRegistryFolder::~CRegistryFolder()
{
TRACE("Destroying CRegistryFolder %p\n", this);
if (m_shellPidl)
ILFree(m_shellPidl);
if (m_PidlManager)
delete m_PidlManager;
}
// IShellFolder