[SHLWAPI][SDK][SHELL32_APITEST][SHLWAPI_WINETEST] Property Bag on Desktop Upgrade (#5590)

- Add CDesktopUpgradePropertyBag class.
- Implement SHGetDesktopUpgradePropertyBag
  function.
CORE-9283
This commit is contained in:
Katayama Hirofumi MZ 2023-08-22 12:01:20 +09:00 committed by GitHub
parent e7cb6f4920
commit a2d8e464c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 221 additions and 3 deletions

View file

@ -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','\\',

View file

@ -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);
}

View file

@ -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;

View file

@ -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)
{

View file

@ -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(