https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a2d8e464c805122243f47…
commit a2d8e464c805122243f474801d2c96f2d40eca8d
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Tue Aug 22 12:01:20 2023 +0900
Commit: GitHub <noreply(a)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(