[BROWSEUI] Implement ACLCustomMRU.
authorMark Jansen <mark.jansen@reactos.org>
Sun, 17 Dec 2017 14:29:30 +0000 (15:29 +0100)
committerMark Jansen <mark.jansen@reactos.org>
Mon, 18 Dec 2017 22:17:17 +0000 (23:17 +0100)
CORE-9281

dll/win32/browseui/ACLCustomMRU.cpp [new file with mode: 0644]
dll/win32/browseui/ACLCustomMRU.h [new file with mode: 0644]
dll/win32/browseui/CMakeLists.txt
dll/win32/browseui/browseui.cpp
dll/win32/browseui/browseui.rc
dll/win32/browseui/precomp.h
dll/win32/browseui/res/custommru.rgs [new file with mode: 0644]
dll/win32/browseui/resource.h
sdk/include/reactos/browseui_undoc.h
sdk/include/reactos/shlguid_undoc.h

diff --git a/dll/win32/browseui/ACLCustomMRU.cpp b/dll/win32/browseui/ACLCustomMRU.cpp
new file mode 100644 (file)
index 0000000..1f0f03f
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * PROJECT:     ReactOS browseui
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Custom MRU AutoComplete List
+ * COPYRIGHT:   Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
+ */
+
+#include "precomp.h"
+
+CACLCustomMRU::CACLCustomMRU()
+    :m_bDirty(false)
+{
+}
+
+CACLCustomMRU::~CACLCustomMRU()
+{
+    PersistMRU();
+    m_Key.Close();
+}
+
+void CACLCustomMRU::PersistMRU()
+{
+    WCHAR Key[2] = { 0, 0 };
+
+    if (!m_bDirty)
+        return;
+    m_bDirty = false;
+
+    if (m_Key.m_hKey)
+    {
+        m_Key.SetStringValue(L"MRUList", m_MRUList);
+        for (int Index = 0; Index < m_MRUList.GetLength(); ++Index)
+        {
+            Key[0] = Index + 'a';
+            m_Key.SetStringValue(Key, m_MRUData[Index]);
+        }
+    }
+}
+
+// *** IACLCustomMRU methods ***
+HRESULT STDMETHODCALLTYPE CACLCustomMRU::Initialize(LPCWSTR pwszMRURegKey, DWORD dwMax)
+{
+    LSTATUS Status = m_Key.Create(HKEY_CURRENT_USER, pwszMRURegKey);
+    if (Status != ERROR_SUCCESS)
+        return HRESULT_FROM_WIN32(Status);
+
+    m_MRUData.RemoveAll();
+    dwMax = max(0, dwMax);
+    dwMax = min(29, dwMax);
+    while (dwMax--)
+        m_MRUData.Add(CStringW());
+
+    WCHAR MRUList[40];
+    ULONG nChars = _countof(MRUList);
+
+    Status = m_Key.QueryStringValue(L"MRUList", MRUList, &nChars);
+    if (Status != ERROR_SUCCESS)
+        return S_OK;
+
+    if (nChars > 0 && MRUList[nChars-1] == '\0')
+        nChars--;
+
+    if (nChars > (ULONG)m_MRUData.GetSize())
+        return S_OK;
+
+    for (ULONG n = 0; n < nChars; ++n)
+    {
+        if (MRUList[n] >= 'a' && MRUList[n] <= '}' && m_MRUList.Find(MRUList[n]) < 0)
+        {
+            WCHAR Key[2] = { MRUList[n], NULL };
+            WCHAR Value[MAX_PATH * 2];
+            ULONG nValueChars = _countof(Value);
+
+            m_MRUList += MRUList[n];
+            int Index = MRUList[n] - 'a';
+
+            if (Index < m_MRUData.GetSize())
+            {
+                Status = m_Key.QueryStringValue(Key, Value, &nValueChars);
+                if (Status == ERROR_SUCCESS)
+                {
+                    m_MRUData[Index] = CStringW(Value, nValueChars);
+                }
+            }
+        }
+    }
+
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE CACLCustomMRU::AddMRUString(LPCWSTR pwszEntry)
+{
+    ATLASSERT(m_MRUData.GetSize() <= m_MRUList.GetLength());
+
+    m_bDirty = true;
+
+    CStringW NewElement = pwszEntry;
+    WCHAR Key[2] = { 0, 0 };
+    int Index = m_MRUData.Find(NewElement);
+    if (Index >= 0)
+    {
+        /* Move the key to the front */
+        Key[0] = Index + 'a';
+        m_MRUList.Replace(Key, L"");
+        m_MRUList = Key + m_MRUList;
+        return S_OK;
+    }
+
+    int TotalLen = m_MRUList.GetLength();
+    if (m_MRUData.GetSize() == TotalLen)
+    {
+        /* Find oldest element, move that to the front */
+        Key[0] = m_MRUList[TotalLen-1];
+        m_MRUList = Key + m_MRUList.Left(TotalLen-1);
+        Index = Key[0] - 'a';
+    }
+    else
+    {
+        /* Find the first empty entry */
+        for (Index = 0; Index < m_MRUData.GetSize(); ++Index)
+        {
+            if (m_MRUData[Index].IsEmpty())
+                break;
+        }
+        Key[0] = Index + 'a';
+        m_MRUList = Key + m_MRUList;
+    }
+    m_MRUData[Index] = NewElement;
+
+    PersistMRU();
+    return S_OK;
+}
+
diff --git a/dll/win32/browseui/ACLCustomMRU.h b/dll/win32/browseui/ACLCustomMRU.h
new file mode 100644 (file)
index 0000000..7aa9c9b
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * PROJECT:     ReactOS browseui
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Custom MRU AutoComplete List
+ * COPYRIGHT:   Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
+ */
+
+#pragma once
+
+class CACLCustomMRU :
+    public CComCoClass<CACLCustomMRU, &CLSID_ACLCustomMRU>,
+    public CComObjectRootEx<CComMultiThreadModelNoCS>,
+    public IACLCustomMRU
+{
+private:
+    CRegKey m_Key;
+    CStringW m_MRUList;
+    CSimpleArray<CStringW> m_MRUData;
+    bool m_bDirty;
+
+    void PersistMRU();
+
+public:
+    CACLCustomMRU();
+    ~CACLCustomMRU();
+
+    // *** IACLCustomMRU methods ***
+    virtual HRESULT STDMETHODCALLTYPE Initialize(LPCWSTR pwszMRURegKey, DWORD dwMax);
+    virtual HRESULT STDMETHODCALLTYPE AddMRUString(LPCWSTR pwszEntry);
+
+public:
+
+    DECLARE_REGISTRY_RESOURCEID(IDR_ACLCUSTOMMRU)
+    DECLARE_NOT_AGGREGATABLE(CACLCustomMRU)
+
+    DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+    BEGIN_COM_MAP(CACLCustomMRU)
+        COM_INTERFACE_ENTRY_IID(IID_IACLCustomMRU, IACLCustomMRU)
+    END_COM_MAP()
+};
index 45afa68..161c45f 100644 (file)
@@ -4,10 +4,15 @@ add_subdirectory(shellbars)
 
 set_cpp(WITH_RUNTIME)
 
+add_definitions(
+    -D_ATL_NO_EXCEPTIONS)
+
 include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/atl)
 spec2def(browseui.dll browseui.spec ADD_IMPORTLIB)
 
 list(APPEND SOURCE
+    ACLCustomMRU.cpp
+    ACLCustomMRU.h
     aclistisf.cpp
     aclmulti.cpp
     addressband.cpp
index 6832678..98a94c2 100644 (file)
@@ -127,6 +127,7 @@ public:
 
 
 BEGIN_OBJECT_MAP(ObjectMap)
+OBJECT_ENTRY(CLSID_ACLCustomMRU, CACLCustomMRU)
 OBJECT_ENTRY(CLSID_AutoComplete, CAutoComplete)
 OBJECT_ENTRY(CLSID_ACLMulti, CACLMulti)
 OBJECT_ENTRY(CLSID_ACListISF, CACListISF)
index 6badbc9..bece75e 100644 (file)
@@ -46,6 +46,7 @@ IDR_PROGRESSDIALOG REGISTRY "res/progressdialog.rgs"
 IDR_AUTOCOMPLETE REGISTRY "res/autocomplete.rgs"
 IDR_ACLISTISF REGISTRY "res/shellautocomplete.rgs"
 IDR_ISFBAND REGISTRY "res/isfband.rgs"
+IDR_ACLCUSTOMMRU REGISTRY "res/custommru.rgs"
 
 #include <reactos/manifest_dll.rc>
 
index 3303834..5ee3ee0 100644 (file)
@@ -22,6 +22,7 @@
 #include <atlcom.h>
 #include <atlwin.h>
 #include <atlsimpcoll.h>
+#include <atlstr.h>
 #include <undocuser.h>
 #include <perhist.h>
 #include <exdispid.h>
@@ -35,6 +36,7 @@
 
 #include "resource.h"
 
+#include "ACLCustomMRU.h"
 #include "aclistisf.h"
 #include "aclmulti.h"
 #include "addressband.h"
diff --git a/dll/win32/browseui/res/custommru.rgs b/dll/win32/browseui/res/custommru.rgs
new file mode 100644 (file)
index 0000000..a5d12fa
--- /dev/null
@@ -0,0 +1,13 @@
+HKCR
+{
+       NoRemove CLSID
+       {
+               ForceRemove {6935DB93-21E8-4CCC-BEB9-9FE3C77A297A} = s 'Custom MRU AutoComplete List'
+               {
+                       InprocServer32 = s '%MODULE%'
+                       {
+                               val ThreadingModel = s 'Apartment'
+                       }
+               }
+       }
+}
index 24303de..b974515 100644 (file)
 #define IDR_AUTOCOMPLETE         141
 #define IDR_ACLISTISF            142
 #define IDR_ISFBAND              143
+#define IDR_ACLCUSTOMMRU         144
 
 #define IDS_SMALLICONS           12301
 #define IDS_LARGEICONS           12302
index bd6d6fb..4ea2dcf 100644 (file)
@@ -129,6 +129,21 @@ HRESULT WINAPI SHWriteClassesOfCategories(long param8, long paramC, long param10
 BOOL WINAPI SHIsExplorerBrowser(void);
 HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, DWORD dwFlags);
 
+
+#define INTERFACE IACLCustomMRU
+DECLARE_INTERFACE_IID_(IACLCustomMRU, IUnknown, "F729FC5E-8769-4F3E-BDB2-D7B50FD2275B")
+{
+    // *** IUnknown methods ***
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **ppv) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS)PURE;
+    STDMETHOD_(ULONG, Release) (THIS)PURE;
+
+    // *** IACLCustomMRU specific methods ***
+    STDMETHOD(Initialize) (THIS_ LPCWSTR pwszMRURegKey, DWORD dwMax) PURE;
+    STDMETHOD(AddMRUString) (THIS_ LPCWSTR pwszEntry) PURE;
+};
+#undef INTERFACE
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
index 99dc9ec..aaca7a5 100644 (file)
@@ -47,6 +47,8 @@ DEFINE_GUID(CLSID_BrowserBar,              0x9581015C, 0xD08E, 0x11D0, 0x8D, 0x3
 DEFINE_GUID(CGID_DefViewFrame,             0x710EB7A1, 0x45ED, 0x11D0, 0x92, 0x4A, 0x00, 0x20, 0xAF, 0xC7, 0xAC, 0x4D);
 
 // browseui.dll
+DEFINE_GUID(IID_IACLCustomMRU,             0xf729fc5e, 0x8769, 0x4f3e, 0xbd, 0xb2, 0xd7, 0xb5, 0x0f, 0xd2, 0x27, 0x5b);
+
 DEFINE_GUID(CLSID_SH_AddressBand,          0x01E04581, 0x4EEE, 0x11D0, 0xBF, 0xE9, 0x00, 0xAA, 0x00, 0x5B, 0x43, 0x83);
 DEFINE_GUID(CLSID_AddressEditBox,          0xA08C11D2, 0xA228, 0x11D0, 0x82, 0x5B, 0x00, 0xAA, 0x00, 0x5B, 0x43, 0x83);
 DEFINE_GUID(IID_IAddressEditBox,           0xA08C11D1, 0xA228, 0x11D0, 0x82, 0x5B, 0x00, 0xAA, 0x00, 0x5B, 0x43, 0x83);