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

commit a2d8e464c805122243f474801d2c96f2d40eca8d
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Tue Aug 22 12:01:20 2023 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Tue Aug 22 12:01:20 2023 +0900

    [SHLWAPI][SDK][SHELL32_APITEST][SHLWAPI_WINETEST] Property Bag on Desktop 
Upgrade (#5590)
    
    - Add CDesktopUpgradePropertyBag class.
    - Implement SHGetDesktopUpgradePropertyBag
      function.
    CORE-9283
---
 dll/win32/shlwapi/ordinal.c                      |   2 +
 dll/win32/shlwapi/propbag.cpp                    | 195 ++++++++++++++++++++++-
 modules/rostests/apitests/shell32/ShellState.cpp |   3 +-
 modules/rostests/winetests/shlwapi/ordinal.c     |   5 +
 sdk/include/reactos/shlwapi_undoc.h              |  19 +++
 5 files changed, 221 insertions(+), 3 deletions(-)

diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c
index 6f8855fd10a..985b79a9f40 100644
--- a/dll/win32/shlwapi/ordinal.c
+++ b/dll/win32/shlwapi/ordinal.c
@@ -4505,6 +4505,7 @@ BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID 
*pclsid)
  */
 HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create)
 {
+#ifndef __REACTOS__
     enum _shellkey_flags {
         SHKEY_Root_HKCU = 0x1,
         SHKEY_Root_HKLM = 0x2,
@@ -4520,6 +4521,7 @@ HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, 
BOOL create)
         SHKEY_Subkey_MUICache = 0x5000,
         SHKEY_Subkey_FileExts = 0x6000
     };
+#endif
 
     static const WCHAR explorerW[] = {'S','o','f','t','w','a','r','e','\\',
         
'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
diff --git a/dll/win32/shlwapi/propbag.cpp b/dll/win32/shlwapi/propbag.cpp
index ce65aa6c6a0..fbd5b87a49b 100644
--- a/dll/win32/shlwapi/propbag.cpp
+++ b/dll/win32/shlwapi/propbag.cpp
@@ -719,7 +719,7 @@ SHGetIniStringUTF7W(
         return SHGetIniStringW(lpAppName, lpKeyName + 1, lpReturnedString, 
nSize, lpFileName);
 
     return GetPrivateProfileStringW(lpAppName, lpKeyName, L"", 
lpReturnedString, nSize, lpFileName);
-}   
+}
 
 /**************************************************************************
  *  SHSetIniStringUTF7W (SHLWAPI.474)
@@ -995,3 +995,196 @@ SHCreatePropertyBagOnProfileSection(
 
     return pIniPB->QueryInterface(riid, ppvObj);
 }
+
+class CDesktopUpgradePropertyBag : public CBasePropertyBag
+{
+protected:
+    BOOL _AlreadyUpgraded(HKEY hKey);
+    VOID _MarkAsUpgraded(HKEY hkey);
+    HRESULT _ReadFlags(VARIANT *pvari);
+    HRESULT _ReadItemPositions(VARIANT *pvari);
+    IStream* _GetOldDesktopViewStream();
+    IStream* _NewStreamFromOld(IStream *pOldStream);
+
+public:
+    CDesktopUpgradePropertyBag() : CBasePropertyBag(0) { }
+
+    STDMETHODIMP Read(
+        _In_z_ LPCWSTR pszPropName,
+        _Inout_ VARIANT *pvari,
+        _Inout_opt_ IErrorLog *pErrorLog) override;
+
+    STDMETHODIMP Write(_In_z_ LPCWSTR pszPropName, _In_ VARIANT *pvari) 
override
+    {
+        return E_NOTIMPL;
+    }
+};
+
+VOID CDesktopUpgradePropertyBag::_MarkAsUpgraded(HKEY hkey)
+{
+    DWORD dwValue = TRUE;
+    SHSetValueW(hkey, NULL, L"Upgrade", REG_DWORD, &dwValue, sizeof(dwValue));
+}
+
+BOOL CDesktopUpgradePropertyBag::_AlreadyUpgraded(HKEY hKey)
+{
+    // Check the existence of the value written in _MarkAsUpgraded.
+    DWORD dwValue, cbData = sizeof(dwValue);
+    return SHGetValueW(hKey, NULL, L"Upgrade", NULL, &dwValue, &cbData) == 
ERROR_SUCCESS;
+}
+
+typedef DWORDLONG DESKVIEW_FLAGS; // 64-bit data
+
+HRESULT CDesktopUpgradePropertyBag::_ReadFlags(VARIANT *pvari)
+{
+    DESKVIEW_FLAGS Flags;
+    DWORD cbValue = sizeof(Flags);
+    if (SHGetValueW(HKEY_CURRENT_USER,
+                    
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DeskView",
+                    L"Settings",
+                    NULL,
+                    &Flags,
+                    &cbValue) != ERROR_SUCCESS || cbValue < sizeof(Flags))
+    {
+        return E_FAIL;
+    }
+
+    V_UINT(pvari) = ((UINT)(Flags >> 32)) | 0x220; // FIXME: Magic number
+    V_VT(pvari) = VT_UINT;
+    return S_OK;
+}
+
+typedef struct tagOLD_STREAM_HEADER
+{
+    WORD wMagic;
+    WORD awUnknown[6];
+    WORD wSize;
+} OLD_STREAM_HEADER, *POLD_STREAM_HEADER;
+
+IStream* CDesktopUpgradePropertyBag::_NewStreamFromOld(IStream *pOldStream)
+{
+    OLD_STREAM_HEADER Header;
+    HRESULT hr = pOldStream->Read(&Header, sizeof(Header), NULL);
+    if (FAILED(hr) || Header.wMagic != 28)
+        return NULL;
+
+    // Move stream pointer
+    LARGE_INTEGER li;
+    li.QuadPart = Header.wSize - sizeof(Header);
+    hr = pOldStream->Seek(li, STREAM_SEEK_CUR, NULL);
+    if (FAILED(hr))
+        return NULL;
+
+    // Get the size
+    ULARGE_INTEGER uli;
+    hr = IStream_Size(pOldStream, &uli);
+    if (FAILED(hr))
+        return NULL;
+
+    // Create new stream and attach
+    CComPtr<IStream> pNewStream;
+    pNewStream.Attach(SHCreateMemStream(NULL, 0));
+    if (!pNewStream)
+        return NULL;
+
+    // Subtract Header.wSize from the size
+    uli.QuadPart -= Header.wSize;
+
+    // Copy to pNewStream
+    hr = pOldStream->CopyTo(pNewStream, uli, NULL, NULL);
+    if (FAILED(hr))
+        return NULL;
+
+    li.QuadPart = 0;
+    pNewStream->Seek(li, STREAM_SEEK_SET, NULL);
+
+    return pNewStream.Detach();
+}
+
+IStream* CDesktopUpgradePropertyBag::_GetOldDesktopViewStream()
+{
+    HKEY hKey = SHGetShellKey(SHKEY_Root_HKCU, L"Streams\\Desktop", FALSE);
+    if (!hKey)
+        return NULL;
+
+    CComPtr<IStream> pOldStream;
+    if (!_AlreadyUpgraded(hKey))
+    {
+        pOldStream.Attach(SHOpenRegStream2W(hKey, NULL, L"ViewView2", 0));
+        if (pOldStream)
+        {
+            ULARGE_INTEGER uli;
+            HRESULT hr = IStream_Size(pOldStream, &uli);
+            if (SUCCEEDED(hr) && !uli.QuadPart)
+                pOldStream.Release();
+        }
+
+        if (!pOldStream)
+            pOldStream.Attach(SHOpenRegStream2W(hKey, NULL, L"ViewView", 0));
+
+        _MarkAsUpgraded(hKey);
+    }
+
+    ::RegCloseKey(hKey);
+    return pOldStream.Detach();
+}
+
+HRESULT CDesktopUpgradePropertyBag::_ReadItemPositions(VARIANT *pvari)
+{
+    CComPtr<IStream> pOldStream;
+    pOldStream.Attach(_GetOldDesktopViewStream());
+    if (!pOldStream)
+        return E_FAIL;
+
+    HRESULT hr = E_FAIL;
+    IStream *pNewStream = _NewStreamFromOld(pOldStream);
+    if (pNewStream)
+    {
+        V_UNKNOWN(pvari) = pNewStream;
+        V_VT(pvari) = VT_UNKNOWN;
+        hr = S_OK;
+    }
+
+    return hr;
+}
+
+STDMETHODIMP
+CDesktopUpgradePropertyBag::Read(
+    _In_z_ LPCWSTR pszPropName,
+    _Inout_ VARIANT *pvari,
+    _Inout_opt_ IErrorLog *pErrorLog)
+{
+    UNREFERENCED_PARAMETER(pErrorLog);
+
+    VARTYPE vt = V_VT(pvari);
+
+    HRESULT hr = E_FAIL;
+    if (StrCmpW(L"FFlags", pszPropName) == 0)
+        hr = _ReadFlags(pvari);
+    else if (StrCmpNW(L"ItemPos", pszPropName, 7) == 0)
+        hr = _ReadItemPositions(pvari);
+
+    if (FAILED(hr))
+    {
+        ::VariantInit(pvari);
+        return hr;
+    }
+
+    return ::VariantChangeType(pvari, pvari, 0, vt);
+}
+
+/**************************************************************************
+ *  SHGetDesktopUpgradePropertyBag (Not exported; used in 
CViewStatePropertyBag)
+ *
+ * Creates or gets a property bag object for desktop upgrade
+ *
+ * @param riid    Specifies either IID_IUnknown, IID_IPropertyBag or 
IID_IPropertyBag2.
+ * @param ppvObj  Receives an IPropertyBag pointer.
+ * @return        An HRESULT value. S_OK on success, non-zero on failure.
+ */
+HRESULT SHGetDesktopUpgradePropertyBag(REFIID riid, void **ppvObj)
+{
+    *ppvObj = NULL;
+    CComPtr<CDesktopUpgradePropertyBag> pPropBag(new 
CDesktopUpgradePropertyBag());
+    return pPropBag->QueryInterface(riid, ppvObj);
+}
diff --git a/modules/rostests/apitests/shell32/ShellState.cpp 
b/modules/rostests/apitests/shell32/ShellState.cpp
index 7c50806d2fd..97ae49c719a 100644
--- a/modules/rostests/apitests/shell32/ShellState.cpp
+++ b/modules/rostests/apitests/shell32/ShellState.cpp
@@ -12,6 +12,7 @@
 #include <shellutils.h>
 #include <strsafe.h>
 #include <shlwapi.h>
+#include <shlwapi_undoc.h>
 
 /* [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer] */
 /* The contents of RegValue ShellState. */
@@ -72,8 +73,6 @@ static int read_key(REGSHELLSTATE *prss)
     return 0;
 }
 
-extern "C" HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL 
create);
-
 static int read_advanced_key(SHELLSTATE* pss)
 {
     HKEY hKey;
diff --git a/modules/rostests/winetests/shlwapi/ordinal.c 
b/modules/rostests/winetests/shlwapi/ordinal.c
index cd9231351e6..f4ea269f2ce 100644
--- a/modules/rostests/winetests/shlwapi/ordinal.c
+++ b/modules/rostests/winetests/shlwapi/ordinal.c
@@ -33,6 +33,9 @@
 #include "docobj.h"
 #include "shobjidl.h"
 #include "shlobj.h"
+#ifdef __REACTOS__
+    #include <shlwapi_undoc.h>
+#endif
 
 /* Function ptrs for ordinal calls */
 static HMODULE hShlwapi;
@@ -2796,6 +2799,7 @@ static void test_SHSetIniString(void)
     DeleteFileW(TestIniW);
 }
 
+#ifndef __REACTOS__
 enum _shellkey_flags {
     SHKEY_Root_HKCU = 0x1,
     SHKEY_Root_HKLM = 0x2,
@@ -2811,6 +2815,7 @@ enum _shellkey_flags {
     SHKEY_Subkey_MUICache = 0x5000,
     SHKEY_Subkey_FileExts = 0x6000
 };
+#endif
 
 static void test_SHGetShellKey(void)
 {
diff --git a/sdk/include/reactos/shlwapi_undoc.h 
b/sdk/include/reactos/shlwapi_undoc.h
index 270bc344291..37363db934b 100644
--- a/sdk/include/reactos/shlwapi_undoc.h
+++ b/sdk/include/reactos/shlwapi_undoc.h
@@ -217,6 +217,25 @@ SHSetIniStringUTF7W(
     _In_opt_z_ LPCWSTR lpString,
     _In_z_ LPCWSTR lpFileName);
 
+enum _shellkey_flags
+{
+    SHKEY_Root_HKCU = 0x1,
+    SHKEY_Root_HKLM = 0x2,
+    SHKEY_Key_Explorer = 0x00,
+    SHKEY_Key_Shell = 0x10,
+    SHKEY_Key_ShellNoRoam = 0x20,
+    SHKEY_Key_Classes = 0x30,
+    SHKEY_Subkey_Default = 0x0000,
+    SHKEY_Subkey_ResourceName = 0x1000,
+    SHKEY_Subkey_Handlers = 0x2000,
+    SHKEY_Subkey_Associations = 0x3000,
+    SHKEY_Subkey_Volatile = 0x4000,
+    SHKEY_Subkey_MUICache = 0x5000,
+    SHKEY_Subkey_FileExts = 0x6000
+};
+
+HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create);
+
 int
 WINAPIV
 ShellMessageBoxWrapW(

Reply via email to