https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ad181d892cc5349bba1ac…
commit ad181d892cc5349bba1ac74378a71d7d3d5258cf
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Sun Dec 17 15:29:30 2017 +0100
[BROWSEUI] Implement ACLCustomMRU.
CORE-9281
---
dll/win32/browseui/ACLCustomMRU.cpp | 133 +++++++++++++++++++++++++++++++++++
dll/win32/browseui/ACLCustomMRU.h | 41 +++++++++++
dll/win32/browseui/CMakeLists.txt | 5 ++
dll/win32/browseui/browseui.cpp | 1 +
dll/win32/browseui/browseui.rc | 1 +
dll/win32/browseui/precomp.h | 2 +
dll/win32/browseui/res/custommru.rgs | 13 ++++
dll/win32/browseui/resource.h | 1 +
sdk/include/reactos/browseui_undoc.h | 15 ++++
sdk/include/reactos/shlguid_undoc.h | 2 +
10 files changed, 214 insertions(+)
diff --git a/dll/win32/browseui/ACLCustomMRU.cpp b/dll/win32/browseui/ACLCustomMRU.cpp
new file mode 100644
index 0000000000..1f0f03f29e
--- /dev/null
+++ b/dll/win32/browseui/ACLCustomMRU.cpp
@@ -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(a)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
index 0000000000..7aa9c9b2e6
--- /dev/null
+++ b/dll/win32/browseui/ACLCustomMRU.h
@@ -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(a)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()
+};
diff --git a/dll/win32/browseui/CMakeLists.txt b/dll/win32/browseui/CMakeLists.txt
index 45afa685c4..161c45fb59 100644
--- a/dll/win32/browseui/CMakeLists.txt
+++ b/dll/win32/browseui/CMakeLists.txt
@@ -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
diff --git a/dll/win32/browseui/browseui.cpp b/dll/win32/browseui/browseui.cpp
index 68326784ba..98a94c2369 100644
--- a/dll/win32/browseui/browseui.cpp
+++ b/dll/win32/browseui/browseui.cpp
@@ -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)
diff --git a/dll/win32/browseui/browseui.rc b/dll/win32/browseui/browseui.rc
index 6badbc9fb0..bece75e0c5 100644
--- a/dll/win32/browseui/browseui.rc
+++ b/dll/win32/browseui/browseui.rc
@@ -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>
diff --git a/dll/win32/browseui/precomp.h b/dll/win32/browseui/precomp.h
index 3303834b13..5ee3ee0745 100644
--- a/dll/win32/browseui/precomp.h
+++ b/dll/win32/browseui/precomp.h
@@ -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
index 0000000000..a5d12faf5d
--- /dev/null
+++ b/dll/win32/browseui/res/custommru.rgs
@@ -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'
+ }
+ }
+ }
+}
diff --git a/dll/win32/browseui/resource.h b/dll/win32/browseui/resource.h
index 24303de229..b974515bf2 100644
--- a/dll/win32/browseui/resource.h
+++ b/dll/win32/browseui/resource.h
@@ -103,6 +103,7 @@
#define IDR_AUTOCOMPLETE 141
#define IDR_ACLISTISF 142
#define IDR_ISFBAND 143
+#define IDR_ACLCUSTOMMRU 144
#define IDS_SMALLICONS 12301
#define IDS_LARGEICONS 12302
diff --git a/sdk/include/reactos/browseui_undoc.h b/sdk/include/reactos/browseui_undoc.h
index bd6d6fbc81..4ea2dcf605 100644
--- a/sdk/include/reactos/browseui_undoc.h
+++ b/sdk/include/reactos/browseui_undoc.h
@@ -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) */
diff --git a/sdk/include/reactos/shlguid_undoc.h b/sdk/include/reactos/shlguid_undoc.h
index 99dc9ec8e9..aaca7a5f42 100644
--- a/sdk/include/reactos/shlguid_undoc.h
+++ b/sdk/include/reactos/shlguid_undoc.h
@@ -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);