https://git.reactos.org/?p=reactos.git;a=commitdiff;h=58770200e75bd8f0c4448…
commit 58770200e75bd8f0c44485b0281fbd97fa799406
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Thu Aug 31 09:35:00 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Thu Aug 31 09:35:00 2023 +0900
[SHDOCVW][SDK][COM_APITEST] Implement MRU List for Shell Bag, Part 1 (#5626)
- Add mrulist.cpp source file.
- Add CMruBase, CMruLongList, CMruNode,
and CMruPidlList classes with stub functions.
- Add CLSID_MruPidlList and CLSID_MruLongList.
- Add IMruDataList interface into <shlobj_undoc.h>.
- Add IID_IMruDataList and CLSID_MruLongList
definitions into <shlguid_undoc.h>.
CORE-9283
---
dll/win32/shdocvw/CMakeLists.txt | 1 +
dll/win32/shdocvw/mrulist.cpp | 429 ++++++++++++++++++++++++++++
dll/win32/shdocvw/shdocvw.h | 5 +
dll/win32/shdocvw/shdocvw_main.c | 8 +
modules/rostests/apitests/com/com_apitest.c | 1 +
modules/rostests/apitests/com/com_apitest.h | 1 +
modules/rostests/apitests/com/shdocvw.c | 1 +
sdk/include/reactos/shlguid_undoc.h | 2 +
sdk/include/reactos/shlobj_undoc.h | 41 +++
9 files changed, 489 insertions(+)
diff --git a/dll/win32/shdocvw/CMakeLists.txt b/dll/win32/shdocvw/CMakeLists.txt
index ecc274f294f..307fee5ad6e 100644
--- a/dll/win32/shdocvw/CMakeLists.txt
+++ b/dll/win32/shdocvw/CMakeLists.txt
@@ -17,6 +17,7 @@ set_source_files_properties(shdocvw.rc PROPERTIES OBJECT_DEPENDS
${CMAKE_CURRENT
add_library(shdocvw MODULE
${SOURCE}
+ mrulist.cpp
shdocvw.rc
${CMAKE_CURRENT_BINARY_DIR}/shdocvw.def)
diff --git a/dll/win32/shdocvw/mrulist.cpp b/dll/win32/shdocvw/mrulist.cpp
new file mode 100644
index 00000000000..564c3d9e9be
--- /dev/null
+++ b/dll/win32/shdocvw/mrulist.cpp
@@ -0,0 +1,429 @@
+/*
+ * PROJECT: ReactOS shdocvw
+ * LICENSE: LGPL-2.0-or-later (
https://spdx.org/licenses/LGPL-2.0-or-later)
+ * PURPOSE: Implement MRU List of shdocvw.dll
+ * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
+ */
+
+#define COBJMACROS
+
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <objbase.h>
+#include <oleauto.h>
+#include <shlobj.h>
+#include <shlobj_undoc.h>
+#include <shlguid_undoc.h>
+#include <shlwapi.h>
+#include "shdocvw.h"
+
+#include <wine/debug.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
+
+extern "C" void __cxa_pure_virtual(void)
+{
+ ::DebugBreak();
+}
+
+class CMruBase
+ : public IMruDataList
+{
+protected:
+ LONG m_cRefs = 1; // Reference count
+ DWORD m_dwFlags = 0; // The flags
+ BOOL m_bFlag1 = FALSE; // ???
+ BOOL m_bChecked = FALSE; // ???
+ 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
+
+public:
+ CMruBase()
+ {
+ }
+ virtual ~CMruBase();
+
+ // IUnknown methods
+ STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj) override;
+ STDMETHODIMP_(ULONG) AddRef() override
+ {
+ return ::InterlockedIncrement(&m_cRefs);
+ }
+ STDMETHODIMP_(ULONG) Release() override
+ {
+ if (::InterlockedDecrement(&m_cRefs) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return m_cRefs;
+ }
+
+ // IMruDataList methods
+ STDMETHODIMP InitData(UINT cCapacity, UINT flags, HKEY hKey, LPCWSTR pszSubKey,
+ SLOTCOMPARE fnCompare) 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;
+ STDMETHODIMP QueryInfo(UINT iSlot, UINT *puSlot, DWORD *pcbData) override;
+ STDMETHODIMP Delete(UINT iSlot) override;
+
+ // Non-standard methods
+ virtual HRESULT _IsEqual(const SLOTITEMDATA *pSlot, LPCITEMIDLIST pidl, UINT cbPidl)
const;
+ virtual HRESULT _DeleteValue(LPCWSTR pszValue);
+ virtual HRESULT _InitSlots() = 0;
+ virtual void _SaveSlots() = 0;
+ virtual UINT _UpdateSlots(UINT iSlot) = 0;
+ virtual void _SlotString(DWORD dwSlot, LPWSTR psz, DWORD cch) = 0;
+ virtual HRESULT _GetSlot(UINT iSlot, UINT *puSlot) = 0;
+ virtual HRESULT _RemoveSlot(UINT iSlot, UINT *uSlot) = 0;
+
+ static void* operator new(size_t size)
+ {
+ return ::LocalAlloc(LPTR, size);
+ }
+ static void operator delete(void *ptr)
+ {
+ ::LocalFree(ptr);
+ }
+};
+
+CMruBase::~CMruBase()
+{
+ if (m_hKey)
+ {
+ ::RegCloseKey(m_hKey);
+ m_hKey = NULL;
+ }
+
+ if (m_pSlots)
+ {
+ for (UINT iSlot = 0; iSlot < m_cSlots; ++iSlot)
+ {
+ if (m_pSlots[iSlot].pidl)
+ {
+ ::LocalFree(m_pSlots[iSlot].pidl);
+ m_pSlots[iSlot].pidl = NULL;
+ }
+ }
+
+ ::LocalFree(m_pSlots);
+ m_pSlots = NULL;
+ }
+}
+
+STDMETHODIMP CMruBase::QueryInterface(REFIID riid, void **ppvObj)
+{
+ if (!ppvObj)
+ return E_POINTER;
+ if (IsEqualGUID(riid, IID_IMruDataList))
+ {
+ *ppvObj = static_cast<IMruDataList*>(this);
+ AddRef();
+ return S_OK;
+ }
+ ERR("%s: E_NOINTERFACE\n", debugstr_guid(&riid));
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP
+CMruBase::InitData(
+ UINT cCapacity,
+ UINT flags,
+ HKEY hKey,
+ LPCWSTR pszSubKey,
+ SLOTCOMPARE fnCompare)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CMruBase::AddData(const BYTE *pbData, DWORD cbData, UINT *piSlot)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CMruBase::FindData(const BYTE *pbData, DWORD cbData, UINT *piSlot)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CMruBase::GetData(UINT iSlot, BYTE *pbData, DWORD cbData)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CMruBase::QueryInfo(UINT iSlot, UINT *puSlot, DWORD *pcbData)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CMruBase::Delete(UINT iSlot)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+HRESULT CMruBase::_IsEqual(const SLOTITEMDATA *pSlot, LPCITEMIDLIST pidl, UINT cbPidl)
const
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+HRESULT CMruBase::_DeleteValue(LPCWSTR pszValue)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+class CMruLongList
+ : public CMruBase
+{
+protected:
+ UINT *m_puSlotData = NULL; // The slot data
+
+ void _ImportShortList();
+
+ HRESULT _InitSlots() override;
+ void _SaveSlots() override;
+ UINT _UpdateSlots(UINT iSlot) override;
+ void _SlotString(DWORD dwSlot, LPWSTR psz, DWORD cch) override;
+ HRESULT _GetSlot(UINT iSlot, UINT *puSlot) override;
+ HRESULT _RemoveSlot(UINT iSlot, UINT *uSlot) override;
+
+public:
+ CMruLongList()
+ {
+ }
+
+ ~CMruLongList() override
+ {
+ if (m_puSlotData)
+ {
+ ::LocalFree(m_puSlotData);
+ m_puSlotData = NULL;
+ }
+ }
+};
+
+HRESULT CMruLongList::_InitSlots()
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+void CMruLongList::_SaveSlots()
+{
+ FIXME("Stub\n");
+}
+
+UINT CMruLongList::_UpdateSlots(UINT iSlot)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+void CMruLongList::_SlotString(DWORD dwSlot, LPWSTR psz, DWORD cch)
+{
+ FIXME("Stub\n");
+}
+
+HRESULT CMruLongList::_GetSlot(UINT iSlot, UINT *puSlot)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+HRESULT CMruLongList::_RemoveSlot(UINT iSlot, UINT *uSlot)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+void CMruLongList::_ImportShortList()
+{
+ FIXME("Stub\n");
+}
+
+EXTERN_C HRESULT
+CMruLongList_CreateInstance(DWORD dwUnused1, void **ppv, DWORD dwUnused3)
+{
+ UNREFERENCED_PARAMETER(dwUnused1);
+ UNREFERENCED_PARAMETER(dwUnused3);
+
+ CMruLongList *pMruList = new CMruLongList();
+ *ppv = static_cast<IMruDataList*>(pMruList);
+ return S_OK;
+}
+
+class CMruNode
+ : public CMruLongList
+{
+protected:
+ UINT m_uSlotData = 0; // The slot data
+ CMruNode *m_pParent = NULL; // The parent
+ IShellFolder *m_pShellFolder = NULL; // The shell folder
+
+public:
+ CMruNode() { }
+ CMruNode(CMruNode *pParent, UINT uSlotData);
+ ~CMruNode() override;
+
+ CMruNode *GetParent();
+};
+
+CMruNode::CMruNode(CMruNode *pParent, UINT uSlotData)
+{
+ m_uSlotData = uSlotData;
+ m_pParent = pParent;
+ pParent->AddRef();
+}
+
+CMruNode::~CMruNode()
+{
+ if (m_pParent)
+ {
+ m_pParent->Release();
+ m_pParent = NULL;
+ }
+
+ if (m_pShellFolder)
+ {
+ m_pShellFolder->Release();
+ m_pShellFolder = NULL;
+ }
+}
+
+CMruNode *CMruNode::GetParent()
+{
+ if (m_pParent)
+ m_pParent->AddRef();
+ return m_pParent;
+}
+
+class CMruPidlList
+ : public IMruPidlList
+ , public CMruNode
+{
+protected:
+ LPBYTE m_pbSlots = NULL; // The data
+ DWORD m_cbSlots = 0; // The data size
+ HANDLE m_hMutex = NULL; // The mutex (for sync)
+
+ BOOL _LoadNodeSlots()
+ {
+ DWORD cbSlots = m_cbSlots;
+ 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:
+ CMruPidlList()
+ {
+ }
+
+ virtual ~CMruPidlList()
+ {
+ m_pbSlots = (LPBYTE)::LocalFree(m_pbSlots);
+ if (m_hMutex)
+ {
+ ::CloseHandle(m_hMutex);
+ m_hMutex = NULL;
+ }
+ }
+
+ // IUnknown methods
+ STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj) override;
+ STDMETHODIMP_(ULONG) AddRef() override
+ {
+ return CMruBase::AddRef();
+ }
+ STDMETHODIMP_(ULONG) Release() override
+ {
+ return CMruBase::Release();
+ }
+
+ // IMruPidlList methods
+ STDMETHODIMP InitList(UINT cMRUSize, HKEY hKey, LPCWSTR pszName) override;
+ STDMETHODIMP UsePidl(LPCITEMIDLIST pidl, UINT *puSlots) override;
+ STDMETHODIMP QueryPidl(
+ LPCITEMIDLIST pidl,
+ UINT cSlots,
+ UINT *puSlots,
+ UINT *pcSlots) override;
+ STDMETHODIMP PruneKids(LPCITEMIDLIST pidl) override;
+};
+
+STDMETHODIMP CMruPidlList::QueryInterface(REFIID riid, void **ppvObj)
+{
+ if (!ppvObj)
+ return E_POINTER;
+
+ if (::IsEqualGUID(riid, IID_IMruPidlList) || ::IsEqualGUID(riid, IID_IUnknown))
+ {
+ *ppvObj = static_cast<IMruPidlList*>(this);
+ AddRef();
+ return S_OK;
+ }
+
+ ERR("%s: E_NOINTERFACE\n", debugstr_guid(&riid));
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP CMruPidlList::InitList(UINT cMRUSize, HKEY hKey, LPCWSTR pszName)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CMruPidlList::UsePidl(LPCITEMIDLIST pidl, UINT *puSlots)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CMruPidlList::QueryPidl(
+ LPCITEMIDLIST pidl,
+ UINT cSlots,
+ UINT *puSlots,
+ UINT *pcSlots)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CMruPidlList::PruneKids(LPCITEMIDLIST pidl)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+EXTERN_C HRESULT CMruPidlList_CreateInstance(DWORD dwUnused1, void **ppv, DWORD
dwUnused3)
+{
+ UNREFERENCED_PARAMETER(dwUnused1);
+ UNREFERENCED_PARAMETER(dwUnused3);
+
+ *ppv = NULL;
+
+ CMruPidlList *pMruList = new CMruPidlList();
+ if (pMruList == NULL)
+ return E_OUTOFMEMORY;
+
+ *ppv = static_cast<IMruPidlList*>(pMruList);
+ return S_OK;
+}
diff --git a/dll/win32/shdocvw/shdocvw.h b/dll/win32/shdocvw/shdocvw.h
index 568fbadfbd6..1d8f807d8de 100644
--- a/dll/win32/shdocvw/shdocvw.h
+++ b/dll/win32/shdocvw/shdocvw.h
@@ -50,4 +50,9 @@ extern LONG SHDOCVW_refCount DECLSPEC_HIDDEN;
static inline void SHDOCVW_LockModule(void) { InterlockedIncrement( &SHDOCVW_refCount
); }
static inline void SHDOCVW_UnlockModule(void) { InterlockedDecrement(
&SHDOCVW_refCount ); }
+#ifdef __REACTOS__
+EXTERN_C HRESULT CMruLongList_CreateInstance(DWORD dwUnused1, void **ppv, DWORD
dwUnused3);
+EXTERN_C HRESULT CMruPidlList_CreateInstance(DWORD dwUnused1, void **ppv, DWORD
dwUnused3);
+#endif
+
#endif /* __WINE_SHDOCVW_H */
diff --git a/dll/win32/shdocvw/shdocvw_main.c b/dll/win32/shdocvw/shdocvw_main.c
index d52961909fc..0ca9d5827a5 100644
--- a/dll/win32/shdocvw/shdocvw_main.c
+++ b/dll/win32/shdocvw/shdocvw_main.c
@@ -30,6 +30,7 @@
#include "winreg.h"
#ifdef __REACTOS__
#include "winnls.h"
+#include <shlguid_undoc.h>
#endif
#include "shlwapi.h"
#include "wininet.h"
@@ -87,6 +88,13 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void
**ppv)
|| IsEqualGUID(&CLSID_TaskbarList, rclsid))
return get_ieframe_object(rclsid, riid, ppv);
+#ifdef __REACTOS__
+ if (IsEqualGUID(&CLSID_MruLongList, rclsid))
+ return CMruLongList_CreateInstance(0, ppv, 0);
+ if (IsEqualGUID(&CLSID_MruPidlList, rclsid))
+ return CMruPidlList_CreateInstance(0, ppv, 0);
+#endif
+
/* As a last resort, figure if the CLSID belongs to a 'Shell Instance Object'
*/
return SHDOCVW_GetShellInstanceObjectClassObject(rclsid, riid, ppv);
}
diff --git a/modules/rostests/apitests/com/com_apitest.c
b/modules/rostests/apitests/com/com_apitest.c
index 3200c556c7c..c60ac28d451 100644
--- a/modules/rostests/apitests/com/com_apitest.c
+++ b/modules/rostests/apitests/com/com_apitest.c
@@ -205,6 +205,7 @@ static KNOWN_INTERFACE KnownInterfaces[] =
{ ID_NAME(IID_IMenuPopup), TRUE },
{ ID_NAME(IID_IModalWindow) },
{ ID_NAME(IID_IMoniker) },
+ { ID_NAME(IID_IMruDataList) },
{ ID_NAME(IID_IMruPidlList) },
{ ID_NAME(IID_IMultiMonitorDockingSite), TRUE },
{ ID_NAME(IID_IMultiQI), TRUE },
diff --git a/modules/rostests/apitests/com/com_apitest.h
b/modules/rostests/apitests/com/com_apitest.h
index c8c8ad08d12..3bbe9e18475 100644
--- a/modules/rostests/apitests/com/com_apitest.h
+++ b/modules/rostests/apitests/com/com_apitest.h
@@ -144,6 +144,7 @@ DEFINE_GUID(IID_IHWEventHandler2, 0xcfcc809f, 0x295d, 0x42e8,
0x9f, 0xf
DEFINE_GUID(IID_IInitializeWithBindCtx, 0x71c0d2bc, 0x726d, 0x45cc, 0xa6, 0xc0, 0x2e,
0x31, 0xc1, 0xdb, 0x21, 0x59);
DEFINE_GUID(IID_IItemNameLimits, 0x1df0d7f1, 0xb267, 0x4d28, 0x8b, 0x10, 0x12,
0xe2, 0x32, 0x02, 0xa5, 0xc4);
DEFINE_GUID(IID_IMruPidlList, 0x47851649, 0xa2ef, 0x4e67, 0xba, 0xec, 0xc6,
0xa1, 0x53, 0xac, 0x72, 0xec);
+DEFINE_GUID(IID_IMruDataList, 0xFE787BCB, 0x0EE8, 0x44FB, 0x8C, 0x89, 0x12,
0xF5, 0x08, 0x91, 0x3C, 0x40);
DEFINE_GUID(IID_IMultiMonitorDockingSite, 0x03879de0, 0xa205, 0x11d0, 0x99, 0xcb, 0x00,
0xc0, 0x4f, 0xd6, 0x55, 0xe1);
DEFINE_GUID(IID_INamespaceWalk, 0x57ced8a7, 0x3f4a, 0x432c, 0x93, 0x50, 0x30,
0xf2, 0x44, 0x83, 0xf7, 0x4f);
DEFINE_GUID(IID_INamespaceWalkCB, 0xd92995f8, 0xcf5e, 0x4a76, 0xbf, 0x59, 0xea,
0xd3, 0x9e, 0xa2, 0xb9, 0x7e);
diff --git a/modules/rostests/apitests/com/shdocvw.c
b/modules/rostests/apitests/com/shdocvw.c
index 34ea3efb43d..2839cc9331a 100644
--- a/modules/rostests/apitests/com/shdocvw.c
+++ b/modules/rostests/apitests/com/shdocvw.c
@@ -85,6 +85,7 @@ static const CLASS_AND_INTERFACES ExpectedInterfaces[] =
{
ID_NAME(CLSID_MruLongList),
{
+ { 0x0, &IID_IMruDataList },
{ 0x0, &IID_IUnknown },
}
},
diff --git a/sdk/include/reactos/shlguid_undoc.h b/sdk/include/reactos/shlguid_undoc.h
index e233df556bd..c6d2295cb30 100644
--- a/sdk/include/reactos/shlguid_undoc.h
+++ b/sdk/include/reactos/shlguid_undoc.h
@@ -144,6 +144,8 @@ DEFINE_GUID(CLSID_CopyToMenu, 0xC2FBB630, 0x2971, 0x11D1,
0xA1, 0x8
DEFINE_GUID(CLSID_MoveToMenu, 0xC2FBB631, 0x2971, 0x11D1, 0xA1, 0x8C, 0x00,
0xC0, 0x4F, 0xD7, 0x5D, 0x13);
DEFINE_GUID(CLSID_MruPidlList, 0x42AEDC87, 0x2188, 0x41FD, 0xB9, 0xA3, 0x0C,
0x96, 0x6F, 0xEA, 0xBE, 0xC1);
DEFINE_GUID(IID_IMruPidlList, 0x47851649, 0xA2EF, 0x4E67, 0xBA, 0xEC, 0xC6,
0xA1, 0x53, 0xAC, 0x72, 0xEC);
+DEFINE_GUID(CLSID_MruLongList, 0x53BD6B4E, 0x3780, 0x4693, 0xAF, 0xC3, 0x71,
0x61, 0xC2, 0xF3, 0xEE, 0x9C);
+DEFINE_GUID(IID_IMruDataList, 0xFE787BCB, 0x0EE8, 0x44FB, 0x8C, 0x89, 0x12,
0xF5, 0x08, 0x91, 0x3C, 0x40);
/* The following list of interfaces was taken from here:
http://www.geoffchappell.com/studies/windows/shell/shell32/interfaces/index… */
DEFINE_GUID(IID_IAggregateFilterCondition, 0x86228AA3, 0xA736, 0x4733, 0xBD, 0x8A, 0x10,
0xA8, 0x3C, 0x69, 0xBF, 0x84);
diff --git a/sdk/include/reactos/shlobj_undoc.h b/sdk/include/reactos/shlobj_undoc.h
index 3ed3b8a8962..33f911e05c7 100644
--- a/sdk/include/reactos/shlobj_undoc.h
+++ b/sdk/include/reactos/shlobj_undoc.h
@@ -26,6 +26,15 @@
extern "C" {
#endif /* defined(__cplusplus) */
+typedef struct tagSLOTITEMDATA
+{
+ DWORD dwFlags;
+ UINT cbPidl;
+ LPITEMIDLIST pidl;
+} SLOTITEMDATA, *PSLOTITEMDATA;
+
+typedef INT (CALLBACK *SLOTCOMPARE)(LPCITEMIDLIST, LPCITEMIDLIST, UINT);
+
/*****************************************************************************
* New shellstate structure
*/
@@ -678,6 +687,38 @@ DECLARE_INTERFACE_(IShellBrowserService, IUnknown)
#define IShellBrowserService_GetPropertyBag(T,a,b,c)
(T)->lpVtbl->GetPropertyBag(T,a,b,c)
#endif
+/*****************************************************************************
+ * IMruDataList interface
+ */
+#define INTERFACE IMruDataList
+DECLARE_INTERFACE_(IMruDataList, IUnknown)
+{
+ /*** IUnknown ***/
+ STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ /*** IMruDataList ***/
+ STDMETHOD(InitData)(THIS_ UINT, UINT, HKEY, LPCWSTR, SLOTCOMPARE) PURE;
+ STDMETHOD(AddData)(THIS_ const BYTE *, DWORD, UINT*) PURE;
+ STDMETHOD(FindData)(THIS_ const BYTE*, DWORD, UINT*) PURE;
+ STDMETHOD(GetData)(THIS_ UINT, BYTE*, DWORD) PURE;
+ STDMETHOD(QueryInfo)(THIS_ UINT, UINT*, DWORD*) PURE;
+ STDMETHOD(Delete)(THIS_ UINT) PURE;
+};
+#undef INTERFACE
+
+#ifdef COBJMACROS
+#define IMruDataList_QueryInterface(T,a,b) (T)->lpVtbl->QueryInterface(T,a,b)
+#define IMruDataList_AddRef(T) (T)->lpVtbl->AddRef(T)
+#define IMruDataList_Release(T) (T)->lpVtbl->Release(T)
+#define IMruDataList_InitData(T,a,b,c,d,e) (T)->lpVtbl->InitData(T,a,b,c,d,e)
+#define IMruDataList_AddData(T,a,b,c) (T)->lpVtbl->AddData(T,a,b,c)
+#define IMruDataList_FindData(T,a,b,c) (T)->lpVtbl->FindData(T,a,b,c)
+#define IMruDataList_GetData(T,a,b,c) (T)->lpVtbl->GetData(T,a,b,c)
+#define IMruDataList_QueryInfo(T,a,b,c) (T)->lpVtbl->QueryInfo(T,a,b,c)
+#define IMruDataList_Delete(T,a) (T)->lpVtbl->Delete(T,a)
+#endif
+
/*****************************************************************************
* IMruPidlList interface
*/