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

View file

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