mirror of
https://github.com/reactos/reactos.git
synced 2025-07-24 16:33:49 +00:00
[SHDOCVW][SDK] Implement MRU List for Shell Bag, Part 2 (#5634)
Follow-up to #5626. - Implement CMruBase class. - Add delay import of shell32. - Add RegCreateKeyExWrapW prototype to <shlobj_undoc.h>. CORE-9283
This commit is contained in:
parent
67645ab7a8
commit
8dbb800358
4 changed files with 268 additions and 42 deletions
|
@ -23,7 +23,7 @@ add_library(shdocvw MODULE
|
|||
|
||||
set_module_type(shdocvw win32dll)
|
||||
target_link_libraries(shdocvw uuid wine)
|
||||
add_delay_importlibs(shdocvw ole32 oleaut32 ieframe)
|
||||
add_delay_importlibs(shdocvw shell32 ole32 oleaut32 ieframe)
|
||||
add_importlibs(shdocvw shlwapi advapi32 msvcrt kernel32 ntdll)
|
||||
add_dependencies(shdocvw stdole2)
|
||||
add_pch(shdocvw precomp.h SOURCE)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <shlobj_undoc.h>
|
||||
#include <shlguid_undoc.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
#include "shdocvw.h"
|
||||
|
||||
#include <wine/debug.h>
|
||||
|
@ -27,20 +28,49 @@ extern "C" void __cxa_pure_virtual(void)
|
|||
::DebugBreak();
|
||||
}
|
||||
|
||||
BOOL IEILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2, BOOL bUnknown)
|
||||
{
|
||||
UINT cb1 = ILGetSize(pidl1), cb2 = ILGetSize(pidl2);
|
||||
if (cb1 == cb2 && memcmp(pidl1, pidl2, cb1) == 0)
|
||||
return TRUE;
|
||||
|
||||
FIXME("%p, %p\n", pidl1, pidl2);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// The flags for SLOTITEMDATA.dwFlags
|
||||
#define SLOT_LOADED 0x1
|
||||
#define SLOT_UNKNOWN_FLAG 0x2
|
||||
|
||||
// The flags for CMruBase.m_dwFlags
|
||||
#define COMPARE_BY_MEMCMP 0x0
|
||||
#define COMPARE_BY_STRCMPIW 0x1
|
||||
#define COMPARE_BY_STRCMPW 0x2
|
||||
#define COMPARE_BY_IEILISEQUAL 0x3
|
||||
#define COMPARE_BY_MASK 0xF
|
||||
|
||||
class CMruBase
|
||||
: public IMruDataList
|
||||
{
|
||||
protected:
|
||||
LONG m_cRefs = 1; // Reference count
|
||||
DWORD m_dwFlags = 0; // The flags
|
||||
DWORD m_dwFlags = 0; // The COMPARE_BY_... flags
|
||||
BOOL m_bFlag1 = FALSE; // ???
|
||||
BOOL m_bChecked = FALSE; // ???
|
||||
BOOL m_bChecked = FALSE; // The checked flag
|
||||
HKEY m_hKey = NULL; // A registry key
|
||||
DWORD m_cSlotRooms = 0; // Rooms for slots
|
||||
DWORD m_cSlots = 0; // The # of slots
|
||||
SLOTCOMPARE m_fnCompare = NULL; // The comparison function
|
||||
SLOTITEMDATA * m_pSlots = NULL; // Slot data
|
||||
|
||||
HRESULT _LoadItem(UINT iSlot);
|
||||
HRESULT _AddItem(UINT iSlot, const BYTE *pbData, DWORD cbData);
|
||||
HRESULT _GetItem(UINT iSlot, SLOTITEMDATA **ppItem);
|
||||
void _DeleteItem(UINT iSlot);
|
||||
|
||||
HRESULT _GetSlotItem(UINT iSlot, SLOTITEMDATA **ppItem);
|
||||
void _CheckUsedSlots();
|
||||
|
||||
public:
|
||||
CMruBase()
|
||||
{
|
||||
|
@ -53,19 +83,12 @@ public:
|
|||
{
|
||||
return ::InterlockedIncrement(&m_cRefs);
|
||||
}
|
||||
STDMETHODIMP_(ULONG) Release() override
|
||||
{
|
||||
if (::InterlockedDecrement(&m_cRefs) == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return m_cRefs;
|
||||
}
|
||||
STDMETHODIMP_(ULONG) Release() override;
|
||||
|
||||
// IMruDataList methods
|
||||
STDMETHODIMP InitData(UINT cCapacity, UINT flags, HKEY hKey, LPCWSTR pszSubKey,
|
||||
SLOTCOMPARE fnCompare) override;
|
||||
STDMETHODIMP InitData(UINT cCapacity, UINT flags, HKEY hKey,
|
||||
LPCWSTR pszSubKey OPTIONAL,
|
||||
SLOTCOMPARE fnCompare OPTIONAL) override;
|
||||
STDMETHODIMP AddData(const BYTE *pbData, DWORD cbData, UINT *piSlot) override;
|
||||
STDMETHODIMP FindData(const BYTE *pbData, DWORD cbData, UINT *piSlot) override;
|
||||
STDMETHODIMP GetData(UINT iSlot, BYTE *pbData, DWORD cbData) override;
|
||||
|
@ -73,7 +96,7 @@ public:
|
|||
STDMETHODIMP Delete(UINT iSlot) override;
|
||||
|
||||
// Non-standard methods
|
||||
virtual HRESULT _IsEqual(const SLOTITEMDATA *pSlot, LPCITEMIDLIST pidl, UINT cbPidl) const;
|
||||
virtual BOOL _IsEqual(const SLOTITEMDATA *pItem, LPCVOID pvData, UINT cbData) const;
|
||||
virtual HRESULT _DeleteValue(LPCWSTR pszValue);
|
||||
virtual HRESULT _InitSlots() = 0;
|
||||
virtual void _SaveSlots() = 0;
|
||||
|
@ -104,11 +127,7 @@ CMruBase::~CMruBase()
|
|||
{
|
||||
for (UINT iSlot = 0; iSlot < m_cSlots; ++iSlot)
|
||||
{
|
||||
if (m_pSlots[iSlot].pidl)
|
||||
{
|
||||
::LocalFree(m_pSlots[iSlot].pidl);
|
||||
m_pSlots[iSlot].pidl = NULL;
|
||||
}
|
||||
m_pSlots[iSlot].pvData = ::LocalFree(m_pSlots[iSlot].pvData);
|
||||
}
|
||||
|
||||
::LocalFree(m_pSlots);
|
||||
|
@ -130,58 +149,252 @@ STDMETHODIMP CMruBase::QueryInterface(REFIID riid, void **ppvObj)
|
|||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CMruBase::Release()
|
||||
{
|
||||
if (::InterlockedDecrement(&m_cRefs) == 0)
|
||||
{
|
||||
_SaveSlots();
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return m_cRefs;
|
||||
}
|
||||
|
||||
HRESULT CMruBase::_LoadItem(UINT iSlot)
|
||||
{
|
||||
DWORD cbData;
|
||||
WCHAR szValue[12];
|
||||
|
||||
SLOTITEMDATA *pItem = &m_pSlots[iSlot];
|
||||
_SlotString(iSlot, szValue, _countof(szValue));
|
||||
|
||||
if (SHGetValueW(m_hKey, NULL, szValue, NULL, NULL, &cbData) == ERROR_SUCCESS &&
|
||||
cbData > 0)
|
||||
{
|
||||
pItem->pvData = ::LocalAlloc(LPTR, cbData);
|
||||
if (pItem->pvData)
|
||||
{
|
||||
pItem->cbData = cbData;
|
||||
if (SHGetValueW(m_hKey, NULL, szValue, NULL, pItem->pvData, &cbData) != ERROR_SUCCESS)
|
||||
pItem->pvData = ::LocalFree(pItem->pvData);
|
||||
}
|
||||
}
|
||||
|
||||
pItem->dwFlags |= SLOT_LOADED;
|
||||
if (!pItem->pvData)
|
||||
return E_FAIL;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CMruBase::_GetSlotItem(UINT iSlot, SLOTITEMDATA **ppItem)
|
||||
{
|
||||
if (!(m_pSlots[iSlot].dwFlags & SLOT_LOADED))
|
||||
_LoadItem(iSlot);
|
||||
|
||||
SLOTITEMDATA *pItem = &m_pSlots[iSlot];
|
||||
if (!pItem->pvData)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
*ppItem = pItem;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CMruBase::_GetItem(UINT iSlot, SLOTITEMDATA **ppItem)
|
||||
{
|
||||
HRESULT hr = _GetSlot(iSlot, &iSlot);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
return _GetSlotItem(iSlot, ppItem);
|
||||
}
|
||||
|
||||
void CMruBase::_DeleteItem(UINT iSlot)
|
||||
{
|
||||
WCHAR szBuff[12];
|
||||
|
||||
_SlotString(iSlot, szBuff, _countof(szBuff));
|
||||
_DeleteValue(szBuff);
|
||||
|
||||
m_pSlots[iSlot].pvData = ::LocalFree(m_pSlots[iSlot].pvData);
|
||||
}
|
||||
|
||||
void CMruBase::_CheckUsedSlots()
|
||||
{
|
||||
UINT iGotSlot;
|
||||
for (UINT iSlot = 0; iSlot < m_cSlots; ++iSlot)
|
||||
_GetSlot(iSlot, &iGotSlot);
|
||||
|
||||
m_bChecked = TRUE;
|
||||
}
|
||||
|
||||
HRESULT CMruBase::_AddItem(UINT iSlot, const BYTE *pbData, DWORD cbData)
|
||||
{
|
||||
SLOTITEMDATA *pItem = &m_pSlots[iSlot];
|
||||
|
||||
WCHAR szBuff[12];
|
||||
_SlotString(iSlot, szBuff, _countof(szBuff));
|
||||
|
||||
if (SHSetValueW(m_hKey, NULL, szBuff, REG_BINARY, pbData, cbData) != ERROR_SUCCESS)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
if (cbData >= pItem->cbData || !pItem->pvData)
|
||||
{
|
||||
::LocalFree(pItem->pvData);
|
||||
pItem->pvData = ::LocalAlloc(LPTR, cbData);
|
||||
}
|
||||
|
||||
if (!pItem->pvData)
|
||||
return E_FAIL;
|
||||
|
||||
pItem->cbData = cbData;
|
||||
pItem->dwFlags = (SLOT_LOADED | SLOT_UNKNOWN_FLAG);
|
||||
CopyMemory(pItem->pvData, pbData, cbData);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CMruBase::InitData(
|
||||
UINT cCapacity,
|
||||
UINT flags,
|
||||
HKEY hKey,
|
||||
LPCWSTR pszSubKey,
|
||||
SLOTCOMPARE fnCompare)
|
||||
LPCWSTR pszSubKey OPTIONAL,
|
||||
SLOTCOMPARE fnCompare OPTIONAL)
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return E_NOTIMPL;
|
||||
m_dwFlags = flags;
|
||||
m_fnCompare = fnCompare;
|
||||
m_cSlotRooms = cCapacity;
|
||||
|
||||
if (pszSubKey)
|
||||
::RegCreateKeyExWrapW(hKey, pszSubKey, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &m_hKey, NULL);
|
||||
else
|
||||
m_hKey = SHRegDuplicateHKey(hKey);
|
||||
|
||||
if (!m_hKey)
|
||||
return E_FAIL;
|
||||
|
||||
m_pSlots = (SLOTITEMDATA*)::LocalAlloc(LPTR, m_cSlotRooms * sizeof(SLOTITEMDATA));
|
||||
if (!m_pSlots)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
return _InitSlots();
|
||||
}
|
||||
|
||||
STDMETHODIMP CMruBase::AddData(const BYTE *pbData, DWORD cbData, UINT *piSlot)
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return E_NOTIMPL;
|
||||
UINT iSlot;
|
||||
HRESULT hr = FindData(pbData, cbData, &iSlot);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
iSlot = _UpdateSlots(m_cSlots);
|
||||
hr = _AddItem(iSlot, pbData, cbData);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
iSlot = _UpdateSlots(iSlot);
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
if (piSlot)
|
||||
*piSlot = iSlot;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMruBase::FindData(const BYTE *pbData, DWORD cbData, UINT *piSlot)
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return E_NOTIMPL;
|
||||
if (m_cSlots <= 0)
|
||||
return E_FAIL;
|
||||
|
||||
UINT iSlot = 0;
|
||||
SLOTITEMDATA *pItem;
|
||||
while (FAILED(_GetItem(iSlot, &pItem)) || !_IsEqual(pItem, pbData, cbData))
|
||||
{
|
||||
if (++iSlot >= m_cSlots)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*piSlot = iSlot;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMruBase::GetData(UINT iSlot, BYTE *pbData, DWORD cbData)
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return E_NOTIMPL;
|
||||
SLOTITEMDATA *pItem;
|
||||
HRESULT hr = _GetItem(iSlot, &pItem);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (cbData < pItem->cbData)
|
||||
return 0x8007007A; // FIXME: Magic number
|
||||
|
||||
CopyMemory(pbData, pItem->pvData, pItem->cbData);
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMruBase::QueryInfo(UINT iSlot, UINT *puSlot, DWORD *pcbData)
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return E_NOTIMPL;
|
||||
UINT iGotSlot;
|
||||
HRESULT hr = _GetSlot(iSlot, &iGotSlot);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (puSlot)
|
||||
*puSlot = iGotSlot;
|
||||
|
||||
if (pcbData)
|
||||
{
|
||||
SLOTITEMDATA *pItem;
|
||||
hr = _GetSlotItem(iGotSlot, &pItem);
|
||||
if (SUCCEEDED(hr))
|
||||
*pcbData = pItem->cbData;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMruBase::Delete(UINT iSlot)
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return E_NOTIMPL;
|
||||
UINT uSlot;
|
||||
HRESULT hr = _RemoveSlot(iSlot, &uSlot);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
_DeleteItem(uSlot);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CMruBase::_IsEqual(const SLOTITEMDATA *pSlot, LPCITEMIDLIST pidl, UINT cbPidl) const
|
||||
BOOL CMruBase::_IsEqual(const SLOTITEMDATA *pItem, LPCVOID pvData, UINT cbData) const
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return E_NOTIMPL;
|
||||
if (m_fnCompare)
|
||||
return m_fnCompare(pvData, pItem->pvData, cbData) == 0;
|
||||
|
||||
switch (m_dwFlags & COMPARE_BY_MASK)
|
||||
{
|
||||
case COMPARE_BY_MEMCMP:
|
||||
if (pItem->cbData != cbData)
|
||||
return FALSE;
|
||||
return memcmp(pvData, pItem->pvData, cbData) == 0;
|
||||
|
||||
case COMPARE_BY_STRCMPIW:
|
||||
return StrCmpIW((LPCWSTR)pvData, (LPCWSTR)pItem->pvData) == 0;
|
||||
|
||||
case COMPARE_BY_STRCMPW:
|
||||
return StrCmpW((LPCWSTR)pvData, (LPCWSTR)pItem->pvData) == 0;
|
||||
|
||||
case COMPARE_BY_IEILISEQUAL:
|
||||
return IEILIsEqual((LPCITEMIDLIST)pvData, (LPCITEMIDLIST)pItem->pvData, FALSE);
|
||||
|
||||
default:
|
||||
ERR("0x%08X\n", m_dwFlags);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CMruBase::_DeleteValue(LPCWSTR pszValue)
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return E_NOTIMPL;
|
||||
return SHDeleteValueW(m_hKey, NULL, pszValue);
|
||||
}
|
||||
|
||||
class CMruLongList
|
||||
|
|
|
@ -29,11 +29,11 @@ extern "C" {
|
|||
typedef struct tagSLOTITEMDATA
|
||||
{
|
||||
DWORD dwFlags;
|
||||
UINT cbPidl;
|
||||
LPITEMIDLIST pidl;
|
||||
UINT cbData;
|
||||
LPVOID pvData;
|
||||
} SLOTITEMDATA, *PSLOTITEMDATA;
|
||||
|
||||
typedef INT (CALLBACK *SLOTCOMPARE)(LPCITEMIDLIST, LPCITEMIDLIST, UINT);
|
||||
typedef INT (CALLBACK *SLOTCOMPARE)(LPCVOID pvData1, LPCVOID pvData2, UINT cbData);
|
||||
|
||||
/*****************************************************************************
|
||||
* New shellstate structure
|
||||
|
|
|
@ -69,6 +69,19 @@ HRESULT WINAPI SHWriteDataBlockList(IStream* lpStream, LPDBLIST lpList);
|
|||
HRESULT WINAPI SHReadDataBlockList(IStream* lpStream, LPDBLIST* lppList);
|
||||
VOID WINAPI SHFreeDataBlockList(LPDBLIST lpList);
|
||||
|
||||
LONG
|
||||
WINAPI
|
||||
RegCreateKeyExWrapW(
|
||||
_In_ HKEY hKey,
|
||||
_In_ LPCWSTR lpSubKey,
|
||||
_In_ DWORD Reserved,
|
||||
_In_opt_ LPWSTR lpClass,
|
||||
_In_ DWORD dwOptions,
|
||||
_In_ REGSAM samDesired,
|
||||
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
_Out_ PHKEY phkResult,
|
||||
_Out_opt_ LPDWORD lpdwDisposition);
|
||||
|
||||
/* Redirected to kernel32.ExpandEnvironmentStringsA/W */
|
||||
DWORD WINAPI SHExpandEnvironmentStringsA(LPCSTR,LPSTR,DWORD);
|
||||
DWORD WINAPI SHExpandEnvironmentStringsW(LPCWSTR,LPWSTR,DWORD);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue