https://git.reactos.org/?p=reactos.git;a=commitdiff;h=58770200e75bd8f0c44485b0281fbd97fa799406

commit 58770200e75bd8f0c44485b0281fbd97fa799406
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Thu Aug 31 09:35:00 2023 +0900
Commit:     GitHub <nore...@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...@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.htm 
*/
 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
  */

Reply via email to