[SHDOCVW] Implement MRU List for Shell Bag, Part 5 (#5691)

Follow-up to #5686. 
Implement CSafeMutex and CMruPidlList classes.
CORE-9283
This commit is contained in:
Katayama Hirofumi MZ 2023-09-17 19:52:50 +09:00 committed by GitHub
parent 8650eac76c
commit fd626dc163
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 266 additions and 93 deletions

View file

@ -24,6 +24,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(shdocvw); WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
class CSafeMutex;
class CMruBase; class CMruBase;
class CMruShortList; class CMruShortList;
class CMruLongList; class CMruLongList;
@ -57,6 +58,35 @@ BOOL IEILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2, BOOL bUnknown)
#define COMPARE_BY_IEILISEQUAL 0x3 #define COMPARE_BY_IEILISEQUAL 0x3
#define COMPARE_BY_MASK 0xF #define COMPARE_BY_MASK 0xF
class CSafeMutex
{
protected:
HANDLE m_hMutex;
public:
CSafeMutex() : m_hMutex(NULL)
{
}
~CSafeMutex()
{
if (m_hMutex)
{
::ReleaseMutex(m_hMutex);
m_hMutex = NULL;
}
}
HRESULT Enter(HANDLE hMutex)
{
DWORD wait = ::WaitForSingleObject(hMutex, 500);
if (wait != WAIT_OBJECT_0)
return E_FAIL;
m_hMutex = hMutex;
return S_OK;
}
};
class CMruBase class CMruBase
: public IMruDataList : public IMruDataList
{ {
@ -72,7 +102,7 @@ protected:
SLOTITEMDATA * m_pSlots = NULL; // Slot data SLOTITEMDATA * m_pSlots = NULL; // Slot data
HRESULT _LoadItem(UINT iSlot); HRESULT _LoadItem(UINT iSlot);
HRESULT _AddItem(UINT iSlot, const BYTE *pbData, DWORD cbData); HRESULT _AddItem(UINT iSlot, LPCVOID pvData, DWORD cbData);
HRESULT _GetItem(UINT iSlot, SLOTITEMDATA **ppItem); HRESULT _GetItem(UINT iSlot, SLOTITEMDATA **ppItem);
void _DeleteItem(UINT iSlot); void _DeleteItem(UINT iSlot);
@ -96,9 +126,9 @@ public:
STDMETHODIMP InitData(UINT cCapacity, UINT flags, HKEY hKey, STDMETHODIMP InitData(UINT cCapacity, UINT flags, HKEY hKey,
LPCWSTR pszSubKey OPTIONAL, LPCWSTR pszSubKey OPTIONAL,
SLOTCOMPARE fnCompare OPTIONAL) override; SLOTCOMPARE fnCompare OPTIONAL) override;
STDMETHODIMP AddData(const BYTE *pbData, DWORD cbData, UINT *piSlot) override; STDMETHODIMP AddData(LPCVOID pvData, DWORD cbData, UINT *piSlot) override;
STDMETHODIMP FindData(const BYTE *pbData, DWORD cbData, UINT *piSlot) override; STDMETHODIMP FindData(LPCVOID pvData, DWORD cbData, UINT *piSlot) override;
STDMETHODIMP GetData(UINT iSlot, BYTE *pbData, DWORD cbData) override; STDMETHODIMP GetData(UINT iSlot, LPVOID pvData, DWORD cbData) override;
STDMETHODIMP QueryInfo(UINT iSlot, UINT *puSlot, DWORD *pcbData) override; STDMETHODIMP QueryInfo(UINT iSlot, UINT *puSlot, DWORD *pcbData) override;
STDMETHODIMP Delete(UINT iSlot) override; STDMETHODIMP Delete(UINT iSlot) override;
@ -241,14 +271,14 @@ void CMruBase::_CheckUsedSlots()
m_bChecked = TRUE; m_bChecked = TRUE;
} }
HRESULT CMruBase::_AddItem(UINT iSlot, const BYTE *pbData, DWORD cbData) HRESULT CMruBase::_AddItem(UINT iSlot, LPCVOID pvData, DWORD cbData)
{ {
SLOTITEMDATA *pItem = &m_pSlots[iSlot]; SLOTITEMDATA *pItem = &m_pSlots[iSlot];
WCHAR szBuff[12]; WCHAR szBuff[12];
_SlotString(iSlot, szBuff, _countof(szBuff)); _SlotString(iSlot, szBuff, _countof(szBuff));
if (SHSetValueW(m_hKey, NULL, szBuff, REG_BINARY, pbData, cbData) != ERROR_SUCCESS) if (SHSetValueW(m_hKey, NULL, szBuff, REG_BINARY, pvData, cbData) != ERROR_SUCCESS)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (cbData >= pItem->cbData || !pItem->pvData) if (cbData >= pItem->cbData || !pItem->pvData)
@ -262,7 +292,7 @@ HRESULT CMruBase::_AddItem(UINT iSlot, const BYTE *pbData, DWORD cbData)
pItem->cbData = cbData; pItem->cbData = cbData;
pItem->dwFlags = (SLOT_LOADED | SLOT_SET); pItem->dwFlags = (SLOT_LOADED | SLOT_SET);
CopyMemory(pItem->pvData, pbData, cbData); CopyMemory(pItem->pvData, pvData, cbData);
return S_OK; return S_OK;
} }
@ -293,14 +323,14 @@ CMruBase::InitData(
return _InitSlots(); return _InitSlots();
} }
STDMETHODIMP CMruBase::AddData(const BYTE *pbData, DWORD cbData, UINT *piSlot) STDMETHODIMP CMruBase::AddData(LPCVOID pvData, DWORD cbData, UINT *piSlot)
{ {
UINT iSlot; UINT iSlot;
HRESULT hr = FindData(pbData, cbData, &iSlot); HRESULT hr = FindData(pvData, cbData, &iSlot);
if (FAILED(hr)) if (FAILED(hr))
{ {
iSlot = _UpdateSlots(m_cSlots); iSlot = _UpdateSlots(m_cSlots);
hr = _AddItem(iSlot, pbData, cbData); hr = _AddItem(iSlot, pvData, cbData);
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
} }
@ -316,14 +346,14 @@ STDMETHODIMP CMruBase::AddData(const BYTE *pbData, DWORD cbData, UINT *piSlot)
return hr; return hr;
} }
STDMETHODIMP CMruBase::FindData(const BYTE *pbData, DWORD cbData, UINT *piSlot) STDMETHODIMP CMruBase::FindData(LPCVOID pvData, DWORD cbData, UINT *piSlot)
{ {
if (m_cSlots <= 0) if (m_cSlots <= 0)
return E_FAIL; return E_FAIL;
UINT iSlot = 0; UINT iSlot = 0;
SLOTITEMDATA *pItem; SLOTITEMDATA *pItem;
while (FAILED(_GetItem(iSlot, &pItem)) || !_IsEqual(pItem, pbData, cbData)) while (FAILED(_GetItem(iSlot, &pItem)) || !_IsEqual(pItem, pvData, cbData))
{ {
if (++iSlot >= m_cSlots) if (++iSlot >= m_cSlots)
return E_FAIL; return E_FAIL;
@ -333,7 +363,7 @@ STDMETHODIMP CMruBase::FindData(const BYTE *pbData, DWORD cbData, UINT *piSlot)
return S_OK; return S_OK;
} }
STDMETHODIMP CMruBase::GetData(UINT iSlot, BYTE *pbData, DWORD cbData) STDMETHODIMP CMruBase::GetData(UINT iSlot, LPVOID pvData, DWORD cbData)
{ {
SLOTITEMDATA *pItem; SLOTITEMDATA *pItem;
HRESULT hr = _GetItem(iSlot, &pItem); HRESULT hr = _GetItem(iSlot, &pItem);
@ -343,7 +373,7 @@ STDMETHODIMP CMruBase::GetData(UINT iSlot, BYTE *pbData, DWORD cbData)
if (cbData < pItem->cbData) if (cbData < pItem->cbData)
return 0x8007007A; // FIXME: Magic number return 0x8007007A; // FIXME: Magic number
CopyMemory(pbData, pItem->pvData, pItem->cbData); CopyMemory(pvData, pItem->pvData, pItem->cbData);
return hr; return hr;
} }
@ -694,7 +724,7 @@ void CMruLongList::_ImportShortList()
if (FAILED(hr)) if (FAILED(hr))
break; break;
_AddItem(iSlot, (const BYTE*)pItem->pvData, pItem->cbData); _AddItem(iSlot, pItem->pvData, pItem->cbData);
pShortList->_DeleteItem(iSlot); pShortList->_DeleteItem(iSlot);
m_puSlotData[m_cSlots++] = iSlot; m_puSlotData[m_cSlots++] = iSlot;
@ -751,10 +781,10 @@ public:
HRESULT BindToSlot(UINT iSlot, IShellFolder **ppSF); HRESULT BindToSlot(UINT iSlot, IShellFolder **ppSF);
HRESULT GetNode(BOOL bAdd, LPCITEMIDLIST pidl, CMruNode **pNewNode); HRESULT GetNode(BOOL bAdd, LPCITEMIDLIST pidl, CMruNode **pNewNode);
HRESULT GetNodeSlot(UINT *piSlot); HRESULT GetNodeSlot(UINT *pnNodeSlot);
HRESULT SetNodeSlot(UINT iSlot); HRESULT SetNodeSlot(UINT nNodeSlot);
HRESULT RemoveLeast(UINT *piSlot); HRESULT RemoveLeast(UINT *pnNodeSlot);
HRESULT Clear(CMruPidlList *pList); HRESULT Clear(CMruPidlList *pList);
}; };
@ -793,10 +823,10 @@ HRESULT CMruNode::_CreateNode(UINT iSlot, CMruNode **ppNewNode)
if (!pNewNode) if (!pNewNode)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
WCHAR szBuff[12]; WCHAR szSubKey[12];
_SlotString(iSlot, szBuff, _countof(szBuff)); _SlotString(iSlot, szSubKey, _countof(szSubKey));
HRESULT hr = pNewNode->InitData(m_cSlotRooms, 0, m_hKey, szBuff, NULL); HRESULT hr = pNewNode->InitData(m_cSlotRooms, 0, m_hKey, szSubKey, NULL);
if (FAILED(hr)) if (FAILED(hr))
pNewNode->Release(); pNewNode->Release();
else else
@ -876,19 +906,19 @@ BOOL CMruNode::_IsEqual(SLOTITEMDATA *pItem, LPCVOID pvData, UINT cbData)
(LPCITEMIDLIST)pvData) == 0; (LPCITEMIDLIST)pvData) == 0;
} }
HRESULT CMruNode::GetNodeSlot(UINT *piSlot) HRESULT CMruNode::GetNodeSlot(UINT *pnNodeSlot)
{ {
DWORD dwData, cbData = sizeof(dwData); DWORD dwData, cbData = sizeof(dwData);
DWORD error = SHGetValueW(m_hKey, NULL, L"NodeSlot", NULL, &dwData, (piSlot ? &cbData : NULL)); DWORD error = SHGetValueW(m_hKey, NULL, L"NodeSlot", NULL, &dwData, (pnNodeSlot ? &cbData : NULL));
if (error != ERROR_SUCCESS) if (error != ERROR_SUCCESS)
return E_FAIL; return E_FAIL;
*piSlot = (UINT)dwData; *pnNodeSlot = (UINT)dwData;
return S_OK; return S_OK;
} }
HRESULT CMruNode::SetNodeSlot(UINT iSlot) HRESULT CMruNode::SetNodeSlot(UINT nNodeSlot)
{ {
DWORD dwData = iSlot; DWORD dwData = nNodeSlot;
if (SHSetValueW(m_hKey, NULL, L"NodeSlot", REG_DWORD, &dwData, sizeof(dwData)) != ERROR_SUCCESS) if (SHSetValueW(m_hKey, NULL, L"NodeSlot", REG_DWORD, &dwData, sizeof(dwData)) != ERROR_SUCCESS)
return E_FAIL; return E_FAIL;
return S_OK; return S_OK;
@ -896,7 +926,7 @@ HRESULT CMruNode::SetNodeSlot(UINT iSlot)
HRESULT CMruNode::_AddPidl(UINT iSlot, LPCITEMIDLIST pidl) HRESULT CMruNode::_AddPidl(UINT iSlot, LPCITEMIDLIST pidl)
{ {
return CMruBase::_AddItem(iSlot, (const BYTE*)pidl, sizeof(WORD) + pidl->mkid.cb); return CMruBase::_AddItem(iSlot, pidl, sizeof(WORD) + pidl->mkid.cb);
} }
DWORD CMruNode::_DeleteValue(LPCWSTR pszValue) DWORD CMruNode::_DeleteValue(LPCWSTR pszValue)
@ -907,7 +937,7 @@ DWORD CMruNode::_DeleteValue(LPCWSTR pszValue)
HRESULT CMruNode::_FindPidl(LPCITEMIDLIST pidl, UINT *piSlot) HRESULT CMruNode::_FindPidl(LPCITEMIDLIST pidl, UINT *piSlot)
{ {
return FindData((const BYTE *)pidl, sizeof(WORD) + pidl->mkid.cb, piSlot); return FindData(pidl, sizeof(WORD) + pidl->mkid.cb, piSlot);
} }
HRESULT CMruNode::_GetPidlSlot(LPCITEMIDLIST pidl, BOOL bAdd, UINT *piSlot) HRESULT CMruNode::_GetPidlSlot(LPCITEMIDLIST pidl, BOOL bAdd, UINT *piSlot)
@ -933,11 +963,11 @@ HRESULT CMruNode::_GetPidlSlot(LPCITEMIDLIST pidl, BOOL bAdd, UINT *piSlot)
return hr; return hr;
} }
HRESULT CMruNode::RemoveLeast(UINT *piSlot) HRESULT CMruNode::RemoveLeast(UINT *pnNodeSlot)
{ {
if (!m_cSlots) if (!m_cSlots)
{ {
CMruNode::GetNodeSlot(piSlot); GetNodeSlot(pnNodeSlot);
return S_FALSE; return S_FALSE;
} }
@ -947,10 +977,10 @@ HRESULT CMruNode::RemoveLeast(UINT *piSlot)
return hr; return hr;
CMruNode *pNode; CMruNode *pNode;
hr = CMruNode::_CreateNode(uSlot, &pNode); hr = _CreateNode(uSlot, &pNode);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = pNode->RemoveLeast(piSlot); hr = pNode->RemoveLeast(pnNodeSlot);
pNode->Release(); pNode->Release();
} }
@ -965,42 +995,24 @@ HRESULT CMruNode::RemoveLeast(UINT *piSlot)
} }
class CMruPidlList class CMruPidlList
: public IMruPidlList : public CMruNode
, public CMruNode , public IMruPidlList
{ {
protected: protected:
LPBYTE m_pbSlots = NULL; // The data LPBYTE m_pbNodeSlots = NULL; // The node slots (contains SLOT_... flags)
DWORD m_cbSlots = 0; // The data size DWORD m_cMaxNodeSlots = 0; // The upper bound of the node slot index
HANDLE m_hMutex = NULL; // The mutex (for sync) HANDLE m_hMutex = NULL; // The mutex (for sync)
BOOL _LoadNodeSlots() BOOL _LoadNodeSlots();
{ void _SaveNodeSlots();
DWORD cbSlots = m_cbSlots; HRESULT _InitNodeSlots();
if (SHGetValueW(m_hKey, NULL, L"NodeSlots", NULL, m_pbSlots, &cbSlots) != ERROR_SUCCESS)
return FALSE;
m_cbSlots = cbSlots;
return TRUE;
}
void _SaveNodeSlots()
{
SHSetValueW(m_hKey, NULL, L"NodeSlots", REG_BINARY, m_pbSlots, m_cbSlots);
}
public: public:
CMruPidlList() CMruPidlList() { }
{ ~CMruPidlList() override;
}
virtual ~CMruPidlList() HRESULT GetEmptySlot(UINT *pnNodeSlot);
{ void EmptyNodeSlot(UINT nNodeSlot);
m_pbSlots = (LPBYTE)::LocalFree(m_pbSlots);
if (m_hMutex)
{
::CloseHandle(m_hMutex);
m_hMutex = NULL;
}
}
// IUnknown methods // IUnknown methods
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj) override; STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj) override;
@ -1014,18 +1026,26 @@ public:
} }
// IMruPidlList methods // IMruPidlList methods
STDMETHODIMP InitList(UINT cMRUSize, HKEY hKey, LPCWSTR pszName) override; STDMETHODIMP InitList(UINT cMRUSize, HKEY hKey, LPCWSTR pszSubKey) override;
STDMETHODIMP UsePidl(LPCITEMIDLIST pidl, UINT *puSlots) override; STDMETHODIMP UsePidl(LPCITEMIDLIST pidl, UINT *pnNodeSlot) override;
STDMETHODIMP QueryPidl( STDMETHODIMP QueryPidl(
LPCITEMIDLIST pidl, LPCITEMIDLIST pidl,
UINT cSlots, UINT cSlots,
UINT *puSlots, UINT *pnNodeSlots,
UINT *pcSlots) override; UINT *pcNodeSlots) override;
STDMETHODIMP PruneKids(LPCITEMIDLIST pidl) override; STDMETHODIMP PruneKids(LPCITEMIDLIST pidl) override;
void EmptyNodeSlot(UINT iSlot);
}; };
CMruPidlList::~CMruPidlList()
{
m_pbNodeSlots = (LPBYTE)::LocalFree(m_pbNodeSlots);
if (m_hMutex)
{
::CloseHandle(m_hMutex);
m_hMutex = NULL;
}
}
STDMETHODIMP CMruPidlList::QueryInterface(REFIID riid, void **ppvObj) STDMETHODIMP CMruPidlList::QueryInterface(REFIID riid, void **ppvObj)
{ {
if (!ppvObj) if (!ppvObj)
@ -1042,32 +1062,182 @@ STDMETHODIMP CMruPidlList::QueryInterface(REFIID riid, void **ppvObj)
return E_NOINTERFACE; return E_NOINTERFACE;
} }
STDMETHODIMP CMruPidlList::InitList(UINT cMRUSize, HKEY hKey, LPCWSTR pszName) BOOL CMruPidlList::_LoadNodeSlots()
{ {
FIXME("Stub\n"); DWORD cbNodeSlots = m_cSlotRooms * sizeof(BYTE);
return E_NOTIMPL; if (SHGetValueW(m_hKey, NULL, L"NodeSlots", NULL, m_pbNodeSlots, &cbNodeSlots) != ERROR_SUCCESS)
return FALSE;
m_cMaxNodeSlots = m_cSlotRooms;
return TRUE;
} }
STDMETHODIMP CMruPidlList::UsePidl(LPCITEMIDLIST pidl, UINT *puSlots) void CMruPidlList::_SaveNodeSlots()
{ {
FIXME("Stub\n"); DWORD cbNodeSlots = m_cSlotRooms * sizeof(BYTE);
return E_NOTIMPL; SHSetValueW(m_hKey, NULL, L"NodeSlots", REG_BINARY, m_pbNodeSlots, cbNodeSlots);
}
HRESULT CMruPidlList::_InitNodeSlots()
{
m_pbNodeSlots = (BYTE*)LocalAlloc(LPTR, m_cSlotRooms * sizeof(BYTE));
if (!m_pbNodeSlots)
return E_OUTOFMEMORY;
_LoadNodeSlots();
m_bNeedSave = TRUE;
_SaveNodeSlots();
return S_OK;
}
HRESULT CMruPidlList::GetEmptySlot(UINT *pnNodeSlot)
{
*pnNodeSlot = 0;
if (!_LoadNodeSlots())
return E_FAIL;
if (m_cMaxNodeSlots < m_cSlotRooms)
{
m_pbNodeSlots[m_cMaxNodeSlots] = SLOT_SET;
*pnNodeSlot = ++m_cMaxNodeSlots;
_SaveNodeSlots();
return S_OK;
}
for (UINT iNodeSlot = 0; iNodeSlot < m_cMaxNodeSlots; ++iNodeSlot)
{
if (m_pbNodeSlots[iNodeSlot] & SLOT_SET)
continue;
m_pbNodeSlots[iNodeSlot] = SLOT_SET;
*pnNodeSlot = iNodeSlot + 1; // nNodeSlot is 1-base
_SaveNodeSlots();
return S_OK;
}
HRESULT hr = E_FAIL;
if (SUCCEEDED(RemoveLeast(pnNodeSlot)) && *pnNodeSlot)
hr = S_OK;
_SaveNodeSlots();
return hr;
}
STDMETHODIMP CMruPidlList::InitList(UINT cMRUSize, HKEY hKey, LPCWSTR pszSubKey)
{
HRESULT hr = InitData(cMRUSize, 0, hKey, pszSubKey, NULL);
if (FAILED(hr))
return hr;
hr = _InitNodeSlots();
if (FAILED(hr))
return hr;
m_hMutex = ::CreateMutexW(NULL, FALSE, L"Shell.CMruPidlList");
if (!m_hMutex)
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
STDMETHODIMP CMruPidlList::UsePidl(LPCITEMIDLIST pidl, UINT *pnNodeSlot)
{
CSafeMutex mutex;
HRESULT hr = mutex.Enter(m_hMutex);
if (FAILED(hr))
return hr;
*pnNodeSlot = 0;
CMruNode *pNode;
hr = GetNode(TRUE, pidl, &pNode);
if (FAILED(hr))
return hr;
hr = pNode->GetNodeSlot(pnNodeSlot);
if (FAILED(hr))
{
hr = GetEmptySlot(pnNodeSlot);
if (SUCCEEDED(hr))
{
hr = pNode->SetNodeSlot(*pnNodeSlot);
}
}
pNode->Release();
return hr;
} }
STDMETHODIMP CMruPidlList::QueryPidl( STDMETHODIMP CMruPidlList::QueryPidl(
LPCITEMIDLIST pidl, LPCITEMIDLIST pidl,
UINT cSlots, UINT cSlots,
UINT *puSlots, UINT *pnNodeSlots,
UINT *pcSlots) UINT *pcNodeSlots)
{ {
FIXME("Stub\n"); CSafeMutex mutex;
return E_NOTIMPL; HRESULT hr = mutex.Enter(m_hMutex);
if (FAILED(hr))
return hr;
*pcNodeSlots = 0;
CMruNode *pNode;
hr = GetNode(FALSE, pidl, &pNode);
if (FAILED(hr))
return hr;
while (pNode && *pcNodeSlots < cSlots)
{
CMruNode *pParent = pNode->GetParent();
if (SUCCEEDED(pNode->GetNodeSlot(&pnNodeSlots[*pcNodeSlots])))
++(*pcNodeSlots);
else if (hr == S_OK && !*pcNodeSlots)
hr = S_FALSE;
pNode->Release();
pNode = pParent;
}
if (pNode)
pNode->Release();
if (SUCCEEDED(hr) && !*pcNodeSlots)
hr = E_FAIL;
return hr;
} }
STDMETHODIMP CMruPidlList::PruneKids(LPCITEMIDLIST pidl) STDMETHODIMP CMruPidlList::PruneKids(LPCITEMIDLIST pidl)
{ {
FIXME("Stub\n"); CSafeMutex mutex;
return E_NOTIMPL; HRESULT hr = mutex.Enter(m_hMutex);
if (FAILED(hr))
return hr;
if (!_LoadNodeSlots())
return hr;
CMruNode *pNode;
hr = GetNode(FALSE, pidl, &pNode);
if (FAILED(hr))
return hr;
if (hr == S_OK)
hr = pNode->Clear(this);
else
hr = E_FAIL;
pNode->Release();
_SaveNodeSlots();
return hr;
}
void CMruPidlList::EmptyNodeSlot(UINT nNodeSlot)
{
m_pbNodeSlots[nNodeSlot - 1] = 0; // nNodeSlot is 1-base
m_bNeedSave = TRUE;
} }
EXTERN_C HRESULT CMruPidlList_CreateInstance(DWORD_PTR dwUnused1, void **ppv, DWORD_PTR dwUnused3) EXTERN_C HRESULT CMruPidlList_CreateInstance(DWORD_PTR dwUnused1, void **ppv, DWORD_PTR dwUnused3)
@ -1091,29 +1261,27 @@ EXTERN_C HRESULT CMruPidlList_CreateInstance(DWORD_PTR dwUnused1, void **ppv, DW
return S_OK; return S_OK;
} }
void CMruPidlList::EmptyNodeSlot(UINT iSlot)
{
m_pbSlots[iSlot - 1] = 0;
m_bNeedSave = TRUE;
}
HRESULT CMruNode::Clear(CMruPidlList *pList) HRESULT CMruNode::Clear(CMruPidlList *pList)
{ {
UINT uSlot; UINT uSlot, nNodeSlot;
HRESULT hr;
while (SUCCEEDED(_GetSlot(0, &uSlot))) while (SUCCEEDED(_GetSlot(0, &uSlot)))
{ {
CMruNode *pNode; CMruNode *pNode;
if (SUCCEEDED(CMruNode::_CreateNode(uSlot, &pNode))) hr = _CreateNode(uSlot, &pNode);
if (SUCCEEDED(hr))
{ {
UINT iSlot; hr = pNode->GetNodeSlot(&nNodeSlot);
if (SUCCEEDED(pNode->GetNodeSlot(&iSlot))) if (SUCCEEDED(hr))
pList->EmptyNodeSlot(iSlot); pList->EmptyNodeSlot(nNodeSlot);
pNode->Clear(pList); pNode->Clear(pList);
pNode->Release(); pNode->Release();
} }
Delete(0); Delete(0);
} }
return S_OK; return S_OK;
} }

View file

@ -61,6 +61,7 @@ static inline void SHDOCVW_UnlockModule(void) { InterlockedDecrement( &SHDOCVW_r
#ifdef __REACTOS__ #ifdef __REACTOS__
EXTERN_C HRESULT CMruLongList_CreateInstance(DWORD_PTR dwUnused1, void **ppv, DWORD_PTR dwUnused3); EXTERN_C HRESULT CMruLongList_CreateInstance(DWORD_PTR dwUnused1, void **ppv, DWORD_PTR dwUnused3);
EXTERN_C HRESULT CMruPidlList_CreateInstance(DWORD_PTR dwUnused1, void **ppv, DWORD_PTR dwUnused3);
EXTERN_C HRESULT CMruClassFactory_CreateInstance(REFIID riid, void **ppv); EXTERN_C HRESULT CMruClassFactory_CreateInstance(REFIID riid, void **ppv);
#endif #endif

View file

@ -105,6 +105,10 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
{ {
return CMruLongList_CreateInstance(0, ppv, 0); return CMruLongList_CreateInstance(0, ppv, 0);
} }
else if (IsEqualGUID(riid, &IID_IMruPidlList))
{
return CMruPidlList_CreateInstance(0, ppv, 0);
}
#endif #endif
/* As a last resort, figure if the CLSID belongs to a 'Shell Instance Object' */ /* As a last resort, figure if the CLSID belongs to a 'Shell Instance Object' */

View file

@ -699,9 +699,9 @@ DECLARE_INTERFACE_(IMruDataList, IUnknown)
STDMETHOD_(ULONG,Release)(THIS) PURE; STDMETHOD_(ULONG,Release)(THIS) PURE;
/*** IMruDataList ***/ /*** IMruDataList ***/
STDMETHOD(InitData)(THIS_ UINT, UINT, HKEY, LPCWSTR, SLOTCOMPARE) PURE; STDMETHOD(InitData)(THIS_ UINT, UINT, HKEY, LPCWSTR, SLOTCOMPARE) PURE;
STDMETHOD(AddData)(THIS_ const BYTE *, DWORD, UINT*) PURE; STDMETHOD(AddData)(THIS_ LPCVOID , DWORD, UINT*) PURE;
STDMETHOD(FindData)(THIS_ const BYTE*, DWORD, UINT*) PURE; STDMETHOD(FindData)(THIS_ LPCVOID , DWORD, UINT*) PURE;
STDMETHOD(GetData)(THIS_ UINT, BYTE*, DWORD) PURE; STDMETHOD(GetData)(THIS_ UINT, LPVOID, DWORD) PURE;
STDMETHOD(QueryInfo)(THIS_ UINT, UINT*, DWORD*) PURE; STDMETHOD(QueryInfo)(THIS_ UINT, UINT*, DWORD*) PURE;
STDMETHOD(Delete)(THIS_ UINT) PURE; STDMETHOD(Delete)(THIS_ UINT) PURE;
}; };