https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1da71e25196bbe358b5997968eb845783f751e12

commit 1da71e25196bbe358b5997968eb845783f751e12
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Mon Sep 18 20:13:29 2023 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Mon Sep 18 20:13:29 2023 +0900

    [SHDOCVW][SHDOCVW_APITEST] Implement MRU List for Shell Bag, Part 6 (#5699)
    
    Follow-up to #5691. Strengthen shdocvw_apitest
    testcase. Fix CLSID_MruPidlList class.
    CORE-9283
---
 dll/win32/shdocvw/mrulist.cpp                    |  56 ++++--
 dll/win32/shdocvw/shdocvw_v1.rgs                 |   4 +
 modules/rostests/apitests/shdocvw/CMakeLists.txt |   2 +-
 modules/rostests/apitests/shdocvw/MRUList.cpp    | 218 ++++++++++++++++-------
 4 files changed, 204 insertions(+), 76 deletions(-)

diff --git a/dll/win32/shdocvw/mrulist.cpp b/dll/win32/shdocvw/mrulist.cpp
index a81aa01315a..ba3fcb11fc2 100644
--- a/dll/win32/shdocvw/mrulist.cpp
+++ b/dll/win32/shdocvw/mrulist.cpp
@@ -34,6 +34,7 @@ class CMruClassFactory;
 
 extern "C" void __cxa_pure_virtual(void)
 {
+    ERR("__cxa_pure_virtual\n");
     ::DebugBreak();
 }
 
@@ -129,7 +130,7 @@ public:
     STDMETHODIMP AddData(LPCVOID pvData, DWORD cbData, UINT *piSlot) override;
     STDMETHODIMP FindData(LPCVOID pvData, DWORD cbData, UINT *piSlot) override;
     STDMETHODIMP GetData(UINT iSlot, LPVOID pvData, DWORD cbData) override;
-    STDMETHODIMP QueryInfo(UINT iSlot, UINT *puSlot, DWORD *pcbData) override;
+    STDMETHODIMP QueryInfo(UINT iSlot, UINT *piGotSlot, DWORD *pcbData) 
override;
     STDMETHODIMP Delete(UINT iSlot) override;
 
     // Non-standard methods
@@ -172,8 +173,7 @@ CMruBase::~CMruBase()
             m_pSlots[iSlot].pvData = ::LocalFree(m_pSlots[iSlot].pvData);
         }
 
-        ::LocalFree(m_pSlots);
-        m_pSlots = NULL;
+        m_pSlots = (SLOTITEMDATA*)::LocalFree(m_pSlots);
     }
 
     ::InterlockedDecrement(&SHDOCVW_refCount);
@@ -371,21 +371,21 @@ STDMETHODIMP CMruBase::GetData(UINT iSlot, LPVOID pvData, 
DWORD cbData)
         return hr;
 
     if (cbData < pItem->cbData)
-        return 0x8007007A; // FIXME: Magic number
+        return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
 
     CopyMemory(pvData, pItem->pvData, pItem->cbData);
     return hr;
 }
 
-STDMETHODIMP CMruBase::QueryInfo(UINT iSlot, UINT *puSlot, DWORD *pcbData)
+STDMETHODIMP CMruBase::QueryInfo(UINT iSlot, UINT *piGotSlot, DWORD *pcbData)
 {
     UINT iGotSlot;
     HRESULT hr = _GetSlot(iSlot, &iGotSlot);
     if (FAILED(hr))
         return hr;
 
-    if (puSlot)
-        *puSlot = iGotSlot;
+    if (piGotSlot)
+        *piGotSlot = iGotSlot;
 
     if (pcbData)
     {
@@ -604,11 +604,7 @@ public:
 
     ~CMruLongList() override
     {
-        if (m_puSlotData)
-        {
-            ::LocalFree(m_puSlotData);
-            m_puSlotData = NULL;
-        }
+        m_puSlotData = (UINT*)::LocalFree(m_puSlotData);
     }
 };
 
@@ -1067,13 +1063,13 @@ BOOL CMruPidlList::_LoadNodeSlots()
     DWORD cbNodeSlots = m_cSlotRooms * sizeof(BYTE);
     if (SHGetValueW(m_hKey, NULL, L"NodeSlots", NULL, m_pbNodeSlots, 
&cbNodeSlots) != ERROR_SUCCESS)
         return FALSE;
-    m_cMaxNodeSlots = m_cSlotRooms;
+    m_cMaxNodeSlots = cbNodeSlots / sizeof(BYTE);
     return TRUE;
 }
 
 void CMruPidlList::_SaveNodeSlots()
 {
-    DWORD cbNodeSlots = m_cSlotRooms * sizeof(BYTE);
+    DWORD cbNodeSlots = m_cMaxNodeSlots * sizeof(BYTE);
     SHSetValueW(m_hKey, NULL, L"NodeSlots", REG_BINARY, m_pbNodeSlots, 
cbNodeSlots);
 }
 
@@ -1126,34 +1122,53 @@ HRESULT CMruPidlList::GetEmptySlot(UINT *pnNodeSlot)
 
 STDMETHODIMP CMruPidlList::InitList(UINT cMRUSize, HKEY hKey, LPCWSTR 
pszSubKey)
 {
+    TRACE("%p -> %u %p %s\n", this, cMRUSize, hKey, debugstr_w(pszSubKey));
+
     HRESULT hr = InitData(cMRUSize, 0, hKey, pszSubKey, NULL);
     if (FAILED(hr))
+    {
+        ERR("0x%08lX\n", hr);
         return hr;
+    }
 
     hr = _InitNodeSlots();
     if (FAILED(hr))
+    {
+        ERR("0x%08lX\n", hr);
         return hr;
+    }
 
     m_hMutex = ::CreateMutexW(NULL, FALSE, L"Shell.CMruPidlList");
     if (!m_hMutex)
+    {
         hr = HRESULT_FROM_WIN32(GetLastError());
+        ERR("0x%08lX\n", hr);
+    }
 
     return hr;
 }
 
 STDMETHODIMP CMruPidlList::UsePidl(LPCITEMIDLIST pidl, UINT *pnNodeSlot)
 {
+    TRACE("%p -> %p %p\n", this, pidl, pnNodeSlot);
+
     CSafeMutex mutex;
     HRESULT hr = mutex.Enter(m_hMutex);
     if (FAILED(hr))
+    {
+        ERR("0x%08lX\n", hr);
         return hr;
+    }
 
     *pnNodeSlot = 0;
 
     CMruNode *pNode;
     hr = GetNode(TRUE, pidl, &pNode);
     if (FAILED(hr))
+    {
+        ERR("0x%08lX\n", hr);
         return hr;
+    }
 
     hr = pNode->GetNodeSlot(pnNodeSlot);
     if (FAILED(hr))
@@ -1175,17 +1190,25 @@ STDMETHODIMP CMruPidlList::QueryPidl(
     UINT *pnNodeSlots,
     UINT *pcNodeSlots)
 {
+    TRACE("%p -> %p %u %p %p\n", this, pidl, cSlots, pnNodeSlots, pcNodeSlots);
+
     CSafeMutex mutex;
     HRESULT hr = mutex.Enter(m_hMutex);
     if (FAILED(hr))
+    {
+        ERR("0x%08lX\n", hr);
         return hr;
+    }
 
     *pcNodeSlots = 0;
 
     CMruNode *pNode;
     hr = GetNode(FALSE, pidl, &pNode);
     if (FAILED(hr))
+    {
+        ERR("0x%08lX\n", hr);
         return hr;
+    }
 
     while (pNode && *pcNodeSlots < cSlots)
     {
@@ -1210,10 +1233,15 @@ STDMETHODIMP CMruPidlList::QueryPidl(
 
 STDMETHODIMP CMruPidlList::PruneKids(LPCITEMIDLIST pidl)
 {
+    TRACE("%p -> %p\n", this, pidl);
+
     CSafeMutex mutex;
     HRESULT hr = mutex.Enter(m_hMutex);
     if (FAILED(hr))
+    {
+        ERR("0x%08lX\n", hr);
         return hr;
+    }
 
     if (!_LoadNodeSlots())
         return hr;
diff --git a/dll/win32/shdocvw/shdocvw_v1.rgs b/dll/win32/shdocvw/shdocvw_v1.rgs
index 9ad6c4ecd37..24d937e4441 100644
--- a/dll/win32/shdocvw/shdocvw_v1.rgs
+++ b/dll/win32/shdocvw/shdocvw_v1.rgs
@@ -203,6 +203,10 @@ HKCR
         {
             InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' 
}
         }
+        '{42AEDC87-2188-41FD-B9A3-0C966FEABEC1}' = s 'MruPidlList'
+        {
+            InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' 
}
+        }
     }
     'Shell.Explorer.1' = s 'Microsoft Web Browser Version 1'
     {
diff --git a/modules/rostests/apitests/shdocvw/CMakeLists.txt 
b/modules/rostests/apitests/shdocvw/CMakeLists.txt
index 72fcc69af22..3f4c6324b57 100644
--- a/modules/rostests/apitests/shdocvw/CMakeLists.txt
+++ b/modules/rostests/apitests/shdocvw/CMakeLists.txt
@@ -6,5 +6,5 @@ list(APPEND SOURCE
 add_executable(shdocvw_apitest ${SOURCE})
 set_module_type(shdocvw_apitest win32cui)
 target_link_libraries(shdocvw_apitest ${PSEH_LIB} uuid)
-add_importlibs(shdocvw_apitest shlwapi oleaut32 ole32 user32 advapi32 msvcrt 
kernel32)
+add_importlibs(shdocvw_apitest shlwapi shell32 oleaut32 ole32 user32 advapi32 
msvcrt kernel32)
 add_rostests_file(TARGET shdocvw_apitest)
diff --git a/modules/rostests/apitests/shdocvw/MRUList.cpp 
b/modules/rostests/apitests/shdocvw/MRUList.cpp
index 73c110dc68c..a0a1cd6fee2 100644
--- a/modules/rostests/apitests/shdocvw/MRUList.cpp
+++ b/modules/rostests/apitests/shdocvw/MRUList.cpp
@@ -19,10 +19,11 @@
 #include <pseh/pseh2.h>
 
 #define SUBKEY0 L"Software\\MRUListTest"
+#define SUBSUBKEY0 L"Software\\MRUListTest\\0"
 #define TEXT0 L"This is a test."
 #define TEXT1 L"ReactOS rocks!"
 
-static void MRUList_List0(void)
+static void MRUList_DataList_0(void)
 {
     HRESULT hr;
     IMruDataList *pList = NULL;
@@ -64,27 +65,35 @@ static void MRUList_List0(void)
     pList->Release();
 }
 
-static void MRUList_List0_Check(void)
+static INT MRUList_Check(LPCWSTR pszSubKey, LPCWSTR pszValueName, LPCVOID 
pvData, DWORD cbData)
 {
     BYTE abData[512];
-    DWORD cbData, dwType;
+    LONG error;
+    DWORD dwSize = cbData;
 
-    cbData = sizeof(abData);
-    LONG error = SHGetValueW(HKEY_CURRENT_USER, SUBKEY0, L"MRUListEx", 
&dwType, abData, &cbData);
-    ok_long(error, ERROR_SUCCESS);
-    ok_long(dwType, REG_BINARY);
-#if 1
-    ok_int(memcmp(abData, "\x01\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 
12), 0);
-#else
-    for (DWORD i = 0; i < cbData; ++i)
+    error = SHGetValueW(HKEY_CURRENT_USER, pszSubKey, pszValueName, NULL, 
abData, &dwSize);
+    if (error != ERROR_SUCCESS)
+        return -999;
+
+#if 0
+    printf("dwSize: %ld\n", dwSize);
+    for (DWORD i = 0; i < dwSize; ++i)
     {
         printf("%02X ", abData[i]);
     }
     printf("\n");
 #endif
+
+    if (dwSize != cbData)
+        return +999;
+
+    if (!pvData)
+        return TRUE;
+
+    return memcmp(abData, pvData, cbData) == 0;
 }
 
-static void MRUList_List1(void)
+static void MRUList_DataList_1(void)
 {
     HRESULT hr;
     IMruDataList *pList = NULL;
@@ -119,27 +128,7 @@ static void MRUList_List1(void)
     pList->Release();
 }
 
-static void MRUList_List1_Check(void)
-{
-    BYTE abData[512];
-    DWORD cbData, dwType;
-
-    cbData = sizeof(abData);
-    LONG error = SHGetValueW(HKEY_CURRENT_USER, SUBKEY0, L"MRUListEx", 
&dwType, abData, &cbData);
-    ok_long(error, ERROR_SUCCESS);
-    ok_long(dwType, REG_BINARY);
-#if 1
-    ok_int(memcmp(abData, "\x01\x00\x00\x00\xFF\xFF\xFF\xFF", 8), 0);
-#else
-    for (DWORD i = 0; i < cbData; ++i)
-    {
-        printf("%02X ", abData[i]);
-    }
-    printf("\n");
-#endif
-}
-
-static void MRUList_List2(void)
+static void MRUList_DataList_2(void)
 {
     HRESULT hr;
     IMruDataList *pList = NULL;
@@ -172,27 +161,7 @@ static void MRUList_List2(void)
     pList->Release();
 }
 
-static void MRUList_List2_Check(void)
-{
-    BYTE abData[512];
-    DWORD cbData, dwType;
-
-    cbData = sizeof(abData);
-    LONG error = SHGetValueW(HKEY_CURRENT_USER, SUBKEY0, L"MRUListEx", 
&dwType, abData, &cbData);
-    ok_long(error, ERROR_SUCCESS);
-    ok_long(dwType, REG_BINARY);
-#if 1
-    ok_int(memcmp(abData, "\x00\x00\x00\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF", 
12), 0);
-#else
-    for (DWORD i = 0; i < cbData; ++i)
-    {
-        printf("%02X ", abData[i]);
-    }
-    printf("\n");
-#endif
-}
-
-static void MRUList_List(void)
+static void MRUList_DataList(void)
 {
     if (IsWindowsVistaOrGreater())
     {
@@ -209,11 +178,11 @@ static void MRUList_List(void)
     error = SHGetValueW(HKEY_CURRENT_USER, SUBKEY0, NULL, NULL, NULL, NULL);
     ok_long(error, ERROR_SUCCESS);
 
-    MRUList_List0();
-    MRUList_List0_Check();
+    MRUList_DataList_0();
+    ok_int(MRUList_Check(SUBKEY0, L"MRUListEx", 
"\x01\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 12), TRUE);
 
-    MRUList_List1();
-    MRUList_List1_Check();
+    MRUList_DataList_1();
+    ok_int(MRUList_Check(SUBKEY0, L"MRUListEx", 
"\x01\x00\x00\x00\xFF\xFF\xFF\xFF", 8), TRUE);
 
     error = SHDeleteValueW(HKEY_CURRENT_USER, SUBKEY0, L"MRUList");
     ok_long(error, ERROR_FILE_NOT_FOUND);
@@ -227,8 +196,8 @@ static void MRUList_List(void)
     error = SHSetValueW(HKEY_CURRENT_USER, SUBKEY0, L"b", REG_BINARY, L"XYZ", 
4 * sizeof(WCHAR));
     ok_long(error, ERROR_SUCCESS);
 
-    MRUList_List2();
-    MRUList_List2_Check();
+    MRUList_DataList_2();
+    ok_int(MRUList_Check(SUBKEY0, L"MRUListEx", 
"\x00\x00\x00\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF", 12), TRUE);
 
     error = SHDeleteValueW(HKEY_CURRENT_USER, SUBKEY0, L"MRUList");
     ok_long(error, ERROR_FILE_NOT_FOUND);
@@ -238,12 +207,139 @@ static void MRUList_List(void)
     SHDeleteKeyW(HKEY_CURRENT_USER, SUBKEY0);
 }
 
+static void MRUList_PidlList_0(void)
+{
+    HRESULT hr;
+    IMruPidlList *pList = NULL;
+
+    hr = CoCreateInstance(CLSID_MruPidlList, NULL, CLSCTX_INPROC_SERVER,
+                          IID_IMruPidlList, (LPVOID*)&pList);
+    ok_hex(hr, S_OK);
+    if (pList == NULL)
+    {
+        skip("pList was NULL\n");
+        return;
+    }
+
+    LONG error;
+
+    error = SHGetValueW(HKEY_CURRENT_USER, SUBKEY0, NULL, NULL, NULL, NULL);
+    ok_long(error, ERROR_FILE_NOT_FOUND);
+
+    hr = pList->InitList(32, HKEY_CURRENT_USER, SUBKEY0);
+    ok_hex(hr, S_OK);
+
+    error = SHGetValueW(HKEY_CURRENT_USER, SUBKEY0, NULL, NULL, NULL, NULL);
+    ok_long(error, ERROR_FILE_NOT_FOUND);
+
+    LPITEMIDLIST pidl1, pidl2;
+    SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl1);
+    SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL, &pidl2);
+
+    UINT uNodeSlot1 = 0xDEADFACE;
+    hr = pList->UsePidl(pidl1, &uNodeSlot1);
+    ok_hex(uNodeSlot1, 1);
+
+    // "NodeSlot" value
+    ok_int(MRUList_Check(SUBKEY0, L"NodeSlot", "\x01\x00\x00\x00", 4), TRUE);
+
+    // "NodeSlots" value (Not "NodeSlot")
+    ok_int(MRUList_Check(SUBKEY0, L"NodeSlots", "\x02", 1), TRUE);
+
+    UINT uNodeSlot2 = 0xDEADFACE;
+    hr = pList->UsePidl(pidl2, &uNodeSlot2);
+    ok_hex(uNodeSlot2, 2);
+
+    // "0" value
+    ok_int(MRUList_Check(SUBKEY0, L"0", NULL, 22), TRUE);
+
+    // "MRUListEx" value
+    ok_int(MRUList_Check(SUBKEY0, L"MRUListEx", 
"\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 8), TRUE);
+
+    // "NodeSlot" value
+    ok_int(MRUList_Check(SUBKEY0, L"NodeSlot", "\x01\x00\x00\x00", 4), TRUE);
+
+    // "NodeSlots" value
+    ok_int(MRUList_Check(SUBKEY0, L"NodeSlots", "\x02\x02", 2), TRUE);
+
+    // SUBSUBKEY0: "MRUListEx" value
+    ok_int(MRUList_Check(SUBSUBKEY0, L"MRUListEx", "\xFF\xFF\xFF\xFF", 4), 
TRUE);
+
+    // SUBSUBKEY0: "NodeSlot" value
+    ok_int(MRUList_Check(SUBSUBKEY0, L"NodeSlot", "\x02\x00\x00\x00", 4), 
TRUE);
+
+    // QueryPidl
+    UINT anNodeSlot[2], cNodeSlots;
+    FillMemory(anNodeSlot, sizeof(anNodeSlot), 0xCC);
+    cNodeSlots = 0xDEAD;
+    hr = pList->QueryPidl(pidl1, _countof(anNodeSlot), anNodeSlot, 
&cNodeSlots);
+    ok_long(hr, S_OK);
+    ok_int(anNodeSlot[0], 1);
+    ok_int(anNodeSlot[1], 0xCCCCCCCC);
+    ok_int(cNodeSlots, 1);
+
+    hr = pList->PruneKids(pidl1);
+
+    // "MRUListEx" value
+    ok_int(MRUList_Check(SUBKEY0, L"MRUListEx", 
"\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 8), TRUE);
+
+    // "NodeSlot" value
+    ok_int(MRUList_Check(SUBKEY0, L"NodeSlot", "\x01\x00\x00\x00", 4), TRUE);
+
+    // "NodeSlots" value
+    ok_int(MRUList_Check(SUBKEY0, L"NodeSlots", "\x02\x00", 2), TRUE);
+
+    FillMemory(anNodeSlot, sizeof(anNodeSlot), 0xCC);
+    cNodeSlots = 0xBEEF;
+    hr = pList->QueryPidl(pidl1, 0, anNodeSlot, &cNodeSlots);
+    ok_long(hr, E_FAIL);
+    ok_int(anNodeSlot[0], 0xCCCCCCCC);
+    ok_int(anNodeSlot[1], 0xCCCCCCCC);
+    ok_int(cNodeSlots, 0);
+
+    FillMemory(anNodeSlot, sizeof(anNodeSlot), 0xCC);
+    cNodeSlots = 0xDEAD;
+    hr = pList->QueryPidl(pidl1, _countof(anNodeSlot), anNodeSlot, 
&cNodeSlots);
+    ok_long(hr, S_OK);
+    ok_int(anNodeSlot[0], 1);
+    ok_int(anNodeSlot[1], 0xCCCCCCCC);
+    ok_int(cNodeSlots, 1);
+
+    FillMemory(anNodeSlot, sizeof(anNodeSlot), 0xCC);
+    cNodeSlots = 0xDEAD;
+    hr = pList->QueryPidl(pidl2, _countof(anNodeSlot), anNodeSlot, 
&cNodeSlots);
+    ok_long(hr, S_FALSE);
+    ok_int(anNodeSlot[0], 1);
+    ok_int(anNodeSlot[1], 0xCCCCCCCC);
+    ok_int(cNodeSlots, 1);
+
+    pList->Release();
+    ILFree(pidl1);
+    ILFree(pidl2);
+}
+
+static void MRUList_PidlList(void)
+{
+    if (IsWindowsVistaOrGreater())
+    {
+        skip("Vista+ doesn't support CLSID_MruPidlList\n");
+        return;
+    }
+
+    SHDeleteKeyW(HKEY_CURRENT_USER, SUBKEY0);
+
+    MRUList_PidlList_0();
+
+    SHDeleteKeyW(HKEY_CURRENT_USER, SUBKEY0);
+}
+
 START_TEST(MRUList)
 {
     HRESULT hr = CoInitialize(NULL);
     ok_hex(hr, S_OK);
 
-    MRUList_List();
+    MRUList_DataList();
+    MRUList_PidlList();
 
     if (SUCCEEDED(hr))
         CoUninitialize();

Reply via email to