https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bb8cb671b8259b52bf640…
commit bb8cb671b8259b52bf64011657b76244132732e8
Author:     Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Fri Oct 2 21:27:23 2020 +0900
Commit:     GitHub <noreply(a)github.com>
CommitDate: Fri Oct 2 21:27:23 2020 +0900
    [BROWSEUI] Accept TypedURLs to CLSID_ACLCustomMRU (#3250)
    Related to #3249. IACLCustomMRU has a special case of TypedURLs. The TypedURLs key
consists of the registry values of "url1", "url2", "url3"
etc instead of "MRUList", "a", "b" etc. CORE-9281
---
 dll/win32/browseui/ACLCustomMRU.cpp | 127 ++++++++++++++++++++++++++++++++++--
 dll/win32/browseui/ACLCustomMRU.h   |  22 ++++++-
 2 files changed, 142 insertions(+), 7 deletions(-)
diff --git a/dll/win32/browseui/ACLCustomMRU.cpp b/dll/win32/browseui/ACLCustomMRU.cpp
index 1f0f03f29e1..c142397e86f 100644
--- a/dll/win32/browseui/ACLCustomMRU.cpp
+++ b/dll/win32/browseui/ACLCustomMRU.cpp
@@ -3,27 +3,77 @@
  * 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)
+ *              Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz(a)gmail.com)
  */
 #include "precomp.h"
+#define TYPED_URLS_KEY L"Software\\Microsoft\\Internet Explorer\\TypedURLs"
+
 CACLCustomMRU::CACLCustomMRU()
-    :m_bDirty(false)
+    : m_bDirty(false), m_bTypedURLs(FALSE), m_ielt(0)
 {
 }
 CACLCustomMRU::~CACLCustomMRU()
 {
     PersistMRU();
-    m_Key.Close();
+}
+
+STDMETHODIMP CACLCustomMRU::Next(ULONG celt, LPWSTR *rgelt, ULONG *pceltFetched)
+{
+    if (!pceltFetched || !rgelt)
+        return E_POINTER;
+
+    *pceltFetched = 0;
+    if (celt == 0)
+        return S_OK;
+
+    *rgelt = NULL;
+    if (INT(m_ielt) >= m_MRUData.GetSize())
+        return S_FALSE;
+
+    size_t cb = (m_MRUData[m_ielt].GetLength() + 1) * sizeof(WCHAR);
+    LPWSTR psz = (LPWSTR)CoTaskMemAlloc(cb);
+    if (!psz)
+        return S_FALSE;
+
+    CopyMemory(psz, (LPCWSTR)m_MRUData[m_ielt], cb);
+    *rgelt = psz;
+    *pceltFetched = 1;
+    ++m_ielt;
+    return S_OK;
+}
+
+STDMETHODIMP CACLCustomMRU::Skip(ULONG celt)
+{
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CACLCustomMRU::Reset()
+{
+    m_ielt = 0;
+    return S_OK;
+}
+
+STDMETHODIMP CACLCustomMRU::Clone(IEnumString ** ppenum)
+{
+    *ppenum = NULL;
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CACLCustomMRU::Expand(LPCOLESTR pszExpand)
+{
+    return E_NOTIMPL;
 }
 void CACLCustomMRU::PersistMRU()
 {
+    if (!m_bDirty || m_bTypedURLs)
+        return;
+
     WCHAR Key[2] = { 0, 0 };
-    if (!m_bDirty)
-        return;
     m_bDirty = false;
     if (m_Key.m_hKey)
@@ -37,14 +87,78 @@ void CACLCustomMRU::PersistMRU()
     }
 }
+static LSTATUS
+RegQueryCStringW(CRegKey& key, LPCWSTR pszValueName, CStringW& str)
+{
+    // Check type and size
+    DWORD dwType, cbData;
+    LSTATUS ret = key.QueryValue(pszValueName, &dwType, NULL, &cbData);
+    if (ret != ERROR_SUCCESS)
+        return ret;
+    if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
+        return ERROR_INVALID_DATA;
+
+    // Allocate buffer
+    LPWSTR pszBuffer = str.GetBuffer(cbData / sizeof(WCHAR) + 1);
+    if (pszBuffer == NULL)
+        return ERROR_OUTOFMEMORY;
+
+    // Get the data
+    ret = key.QueryValue(pszValueName, NULL, pszBuffer, &cbData);
+
+    // Release buffer
+    str.ReleaseBuffer();
+    return ret;
+}
+
+HRESULT CACLCustomMRU::LoadTypedURLs(DWORD dwMax)
+{
+    dwMax = max(0, dwMax);
+    dwMax = min(29, dwMax);
+
+    WCHAR szName[32];
+    CStringW strData;
+    LSTATUS status;
+    for (DWORD i = 1; i <= dwMax; ++i)
+    {
+        // Build a registry value name
+        StringCbPrintfW(szName, sizeof(szName), L"url%lu", i);
+
+        // Read a registry value
+        status = RegQueryCStringW(m_Key, szName, strData);
+        if (status != ERROR_SUCCESS)
+            break;
+
+        m_MRUData.Add(strData);
+    }
+
+    return S_OK;
+}
+
 // *** IACLCustomMRU methods ***
 HRESULT STDMETHODCALLTYPE CACLCustomMRU::Initialize(LPCWSTR pwszMRURegKey, DWORD dwMax)
 {
+    m_ielt = 0;
+
     LSTATUS Status = m_Key.Create(HKEY_CURRENT_USER, pwszMRURegKey);
     if (Status != ERROR_SUCCESS)
         return HRESULT_FROM_WIN32(Status);
     m_MRUData.RemoveAll();
+    if (lstrcmpiW(pwszMRURegKey, TYPED_URLS_KEY) == 0)
+    {
+        m_bTypedURLs = TRUE;
+        return LoadTypedURLs(dwMax);
+    }
+    else
+    {
+        m_bTypedURLs = FALSE;
+        return LoadMRUList(dwMax);
+    }
+}
+
+HRESULT CACLCustomMRU::LoadMRUList(DWORD dwMax)
+{
     dwMax = max(0, dwMax);
     dwMax = min(29, dwMax);
     while (dwMax--)
@@ -53,7 +167,7 @@ HRESULT STDMETHODCALLTYPE CACLCustomMRU::Initialize(LPCWSTR
pwszMRURegKey, DWORD
     WCHAR MRUList[40];
     ULONG nChars = _countof(MRUList);
-    Status = m_Key.QueryStringValue(L"MRUList", MRUList, &nChars);
+    LSTATUS Status = m_Key.QueryStringValue(L"MRUList", MRUList, &nChars);
     if (Status != ERROR_SUCCESS)
         return S_OK;
@@ -92,6 +206,9 @@ HRESULT STDMETHODCALLTYPE CACLCustomMRU::AddMRUString(LPCWSTR
pwszEntry)
 {
     ATLASSERT(m_MRUData.GetSize() <= m_MRUList.GetLength());
+    if (m_bTypedURLs)
+        return E_FAIL;
+
     m_bDirty = true;
     CStringW NewElement = pwszEntry;
diff --git a/dll/win32/browseui/ACLCustomMRU.h b/dll/win32/browseui/ACLCustomMRU.h
index 7aa9c9b2e68..8ea5a8aeb79 100644
--- a/dll/win32/browseui/ACLCustomMRU.h
+++ b/dll/win32/browseui/ACLCustomMRU.h
@@ -3,6 +3,7 @@
  * 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)
+ *              Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz(a)gmail.com)
  */
 #pragma once
@@ -10,6 +11,8 @@
 class CACLCustomMRU :
     public CComCoClass<CACLCustomMRU, &CLSID_ACLCustomMRU>,
     public CComObjectRootEx<CComMultiThreadModelNoCS>,
+    public IEnumString,
+    public IACList,
     public IACLCustomMRU
 {
 private:
@@ -17,16 +20,29 @@ private:
     CStringW m_MRUList;
     CSimpleArray<CStringW> m_MRUData;
     bool m_bDirty;
+    BOOL m_bTypedURLs;
+    ULONG m_ielt;
     void PersistMRU();
+    HRESULT LoadTypedURLs(DWORD dwMax);
+    HRESULT LoadMRUList(DWORD dwMax);
 public:
     CACLCustomMRU();
     ~CACLCustomMRU();
+    // *** IEnumString methods ***
+    STDMETHODIMP Next(ULONG celt, LPWSTR *rgelt, ULONG *pceltFetched) override;
+    STDMETHODIMP Skip(ULONG celt) override;
+    STDMETHODIMP Reset() override;
+    STDMETHODIMP Clone(IEnumString ** ppenum) override;
+
+    // *** IACList methods ***
+    STDMETHODIMP Expand(LPCOLESTR pszExpand) override;
+
     // *** IACLCustomMRU methods ***
-    virtual HRESULT STDMETHODCALLTYPE Initialize(LPCWSTR pwszMRURegKey, DWORD dwMax);
-    virtual HRESULT STDMETHODCALLTYPE AddMRUString(LPCWSTR pwszEntry);
+    STDMETHODIMP Initialize(LPCWSTR pwszMRURegKey, DWORD dwMax) override;
+    STDMETHODIMP AddMRUString(LPCWSTR pwszEntry) override;
 public:
@@ -36,6 +52,8 @@ public:
     DECLARE_PROTECT_FINAL_CONSTRUCT()
     BEGIN_COM_MAP(CACLCustomMRU)
+        COM_INTERFACE_ENTRY_IID(IID_IEnumString, IEnumString)
+        COM_INTERFACE_ENTRY_IID(IID_IACList, IACList)
         COM_INTERFACE_ENTRY_IID(IID_IACLCustomMRU, IACLCustomMRU)
     END_COM_MAP()
 };