mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-26 19:33:31 +00:00
[SHLWAPI][SDK] Support SHWindowsPolicyGetValue (#9038)
Implementing missing features... JIRA issue: CORE-19278 - Add policy.cpp and modify CMakeLists.txt. - Implement SHWindowsPolicyGetValue function. - Modify shlwapi.spec. - Add some GUIDs into <shlguid_undoc.h>.
This commit is contained in:
@@ -25,6 +25,7 @@ list(APPEND SOURCE
|
||||
|
||||
list(APPEND PCH_SKIP_SOURCE
|
||||
assoc.c
|
||||
policy.cpp
|
||||
propbag.cpp
|
||||
utils.cpp
|
||||
wsprintf.c
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* PROJECT: ReactOS shlwapi
|
||||
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
|
||||
* PURPOSE: Implement SHWindowsPolicyGetValue
|
||||
* COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ ([email protected])
|
||||
*/
|
||||
|
||||
#define _ATL_NO_EXCEPTIONS
|
||||
#include <windef.h>
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
#include <shlguid_undoc.h>
|
||||
#include <atlstr.h>
|
||||
#include <strsafe.h>
|
||||
#include <wine/debug.h>
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(policy);
|
||||
|
||||
typedef enum tagPOLICY_STATE
|
||||
{
|
||||
POLICY_STATE_UNCACHED = 0, // Uncached
|
||||
POLICY_STATE_NOT_FOUND = 1, // Not found
|
||||
POLICY_STATE_CACHED = 2, // Cached
|
||||
} POLICY_STATE;
|
||||
|
||||
// Result
|
||||
typedef struct tagSHPOLICY_RESULT
|
||||
{
|
||||
POLICY_STATE state;
|
||||
DWORD dwValue;
|
||||
} SHPOLICY_RESULT, *PSHPOLICY_RESULT;
|
||||
|
||||
// Constraints
|
||||
typedef struct tagSHPOLICY_CONSTRAINT
|
||||
{
|
||||
WORD wFlags;
|
||||
WORD wMinSize;
|
||||
DWORD dwMin;
|
||||
DWORD dwMax;
|
||||
} SHPOLICY_CONSTRAINT, *PSHPOLICY_CONSTRAINT;
|
||||
|
||||
static const SHPOLICY_CONSTRAINT c_Bool = { SRRF_RT_DWORD, sizeof(DWORD), 0, 1 };
|
||||
static const SHPOLICY_CONSTRAINT c_String = { SRRF_RT_REG_SZ, sizeof(WCHAR), 0, 0 };
|
||||
static const SHPOLICY_CONSTRAINT c_TriValue = { SRRF_RT_DWORD, sizeof(DWORD), 1, 3 };
|
||||
static const SHPOLICY_CONSTRAINT c_Special = { SRRF_RT_DWORD, sizeof(DWORD), 0x1806, 0x1808 };
|
||||
|
||||
// Items
|
||||
typedef struct tagSHPOLICY_ITEM
|
||||
{
|
||||
REFGUID rpolid; // POLID (policy descriptor)
|
||||
PCWSTR pszKeyName;
|
||||
PCWSTR pszValueName;
|
||||
const SHPOLICY_CONSTRAINT *pConstraint;
|
||||
} SHPOLICY_ITEM, *PSHPOLICY_ITEM;
|
||||
|
||||
static const SHPOLICY_ITEM g_PolicyItems[] =
|
||||
{
|
||||
{ POLID_UsePathEnvVarForCommandTemplates, L"Explorer", L"UsePathEnvVarForCommandTemplates",
|
||||
&c_Bool },
|
||||
{ POLID_ScanWithAntiVirus, L"Attachments", L"ScanWithAntiVirus", &c_TriValue },
|
||||
{ POLID_SaveZoneInformation, L"Attachments", L"SaveZoneInformation", &c_TriValue },
|
||||
{ POLID_UseTrustedHandlers, L"Attachments", L"UseTrustedHandlers", &c_TriValue },
|
||||
{ POLID_HideZoneInfoOnProperties, L"Attachments", L"HideZoneInfoOnProperties", &c_Bool },
|
||||
{ POLID_DefaultFileTypeRisk, L"Associations", L"DefaultFileTypeRisk", &c_Special },
|
||||
{ POLID_HighRiskFileTypes, L"Associations", L"HighRiskFileTypes", &c_String },
|
||||
{ POLID_ModRiskFileTypes, L"Associations", L"ModRiskFileTypes", &c_String },
|
||||
{ POLID_LowRiskFileTypes, L"Associations", L"LowRiskFileTypes", &c_String },
|
||||
{ POLID_PreXPSP2ShellProtocolBehavior, L"Explorer", L"PreXPSP2ShellProtocolBehavior", &c_Bool },
|
||||
{ POLID_CompareJunctionness, L"Explorer", L"CompareJunctionness", &c_Bool },
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* CPolicyCache
|
||||
*/
|
||||
class CPolicyCache
|
||||
{
|
||||
public:
|
||||
~CPolicyCache()
|
||||
{
|
||||
LocalFree(m_pResults);
|
||||
|
||||
if (m_hGlobalCounter)
|
||||
CloseHandle(m_hGlobalCounter);
|
||||
}
|
||||
|
||||
static void* operator new(size_t size)
|
||||
{
|
||||
// Returns NULL on failure; caller must check before use.
|
||||
// NOTE: C++ UB if constructor runs on NULL, but ReactOS convention.
|
||||
return LocalAlloc(LPTR, size);
|
||||
}
|
||||
static void operator delete(void *ptr)
|
||||
{
|
||||
LocalFree(ptr);
|
||||
}
|
||||
|
||||
BOOL Initialize(const SHPOLICY_ITEM *pItems, UINT cItems)
|
||||
{
|
||||
m_nCounterValue = MINLONG;
|
||||
m_pszRootKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies";
|
||||
m_pItems = pItems;
|
||||
m_cItems = cItems;
|
||||
m_pResults = (PSHPOLICY_RESULT)LocalAlloc(LPTR, cItems * sizeof(SHPOLICY_RESULT));
|
||||
if (!m_pResults)
|
||||
return FALSE;
|
||||
m_hGlobalCounter = SHGlobalCounterCreate(GUID_Restrictions);
|
||||
if (!m_hGlobalCounter)
|
||||
{
|
||||
LocalFree(m_pResults);
|
||||
m_pResults = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HRESULT GetValue(_In_ REFGUID rpolid, _Out_opt_ PVOID pvValue, _Out_opt_ PDWORD pcbValue);
|
||||
|
||||
protected:
|
||||
LPCWSTR m_pszRootKey;
|
||||
HANDLE m_hGlobalCounter;
|
||||
LONG m_nCounterValue;
|
||||
DWORD m_cItems;
|
||||
const SHPOLICY_ITEM *m_pItems;
|
||||
PSHPOLICY_RESULT m_pResults;
|
||||
|
||||
void _ValidateCachedResults()
|
||||
{
|
||||
LONG Value = SHGlobalCounterGetValue(m_hGlobalCounter);
|
||||
if (m_nCounterValue != Value)
|
||||
{
|
||||
m_nCounterValue = Value;
|
||||
ZeroMemory(m_pResults, m_cItems * sizeof(SHPOLICY_RESULT));
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT _GetValue(
|
||||
_In_ LPCWSTR pszSubKey,
|
||||
_In_ LPCWSTR pszValueName,
|
||||
_In_ const SHPOLICY_CONSTRAINT* pConstraint,
|
||||
_Out_opt_ PDWORD pdwType,
|
||||
_Out_opt_ PVOID pvData,
|
||||
_Inout_opt_ PDWORD pcbData);
|
||||
|
||||
static void _CacheResult(
|
||||
const SHPOLICY_CONSTRAINT *pConstraint,
|
||||
PVOID pvValue,
|
||||
PDWORD pcbValue,
|
||||
PSHPOLICY_RESULT pResult);
|
||||
};
|
||||
|
||||
HRESULT
|
||||
CPolicyCache::GetValue(_In_ REFGUID rpolid, _Out_opt_ PVOID pvValue, _Out_opt_ PDWORD pcbValue)
|
||||
{
|
||||
_ValidateCachedResults();
|
||||
|
||||
if (m_cItems == 0)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
UINT iItem;
|
||||
for (iItem = 0; iItem < m_cItems; ++iItem)
|
||||
{
|
||||
if (IsEqualGUID(m_pItems[iItem].rpolid, rpolid))
|
||||
break;
|
||||
}
|
||||
|
||||
if (iItem >= m_cItems)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
const SHPOLICY_ITEM *pItem = &m_pItems[iItem];
|
||||
PSHPOLICY_RESULT pResult = &m_pResults[iItem];
|
||||
|
||||
if (pResult->state == POLICY_STATE_NOT_FOUND)
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
|
||||
// Use caching only when dealing with DWORD value
|
||||
if (pvValue && pcbValue && *pcbValue == sizeof(DWORD) && pResult->state == POLICY_STATE_CACHED)
|
||||
{
|
||||
*(PDWORD)pvValue = pResult->dwValue;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT hr = _GetValue(pItem->pszKeyName, pItem->pszValueName, pItem->pConstraint, NULL,
|
||||
pvValue, pcbValue);
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|
||||
pResult->state = POLICY_STATE_NOT_FOUND;
|
||||
else if (SUCCEEDED(hr) && pvValue)
|
||||
_CacheResult(pItem->pConstraint, pvValue, pcbValue, pResult);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CPolicyCache::_GetValue(
|
||||
_In_ LPCWSTR pszSubKey,
|
||||
_In_ LPCWSTR pszValueName,
|
||||
_In_ const SHPOLICY_CONSTRAINT* pConstraint,
|
||||
_Out_opt_ PDWORD pdwType,
|
||||
_Out_opt_ PVOID pvData,
|
||||
_Inout_opt_ PDWORD pcbData)
|
||||
{
|
||||
CStringW szFullKey = CStringW(m_pszRootKey) + L"\\" + pszSubKey;
|
||||
|
||||
DWORD cbDataSaved = pcbData ? *pcbData : 0;
|
||||
WORD wFlags = pConstraint->wFlags;
|
||||
|
||||
LSTATUS error = RegGetValueW(HKEY_LOCAL_MACHINE, szFullKey, pszValueName, wFlags, pdwType,
|
||||
pvData, pcbData);
|
||||
if (error == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
if (pcbData)
|
||||
*pcbData = cbDataSaved;
|
||||
error = RegGetValueW(HKEY_CURRENT_USER, szFullKey, pszValueName, wFlags, pdwType,
|
||||
pvData, pcbData);
|
||||
}
|
||||
|
||||
if (error)
|
||||
return HRESULT_FROM_WIN32(error);
|
||||
|
||||
if (!pvData)
|
||||
return S_OK;
|
||||
|
||||
if (pConstraint->wFlags == SRRF_RT_DWORD && pConstraint->wMinSize == sizeof(DWORD))
|
||||
{
|
||||
DWORD dwValue = *(PDWORD)pvData;
|
||||
if (dwValue < pConstraint->dwMin || pConstraint->dwMax < dwValue)
|
||||
return E_DATATYPE_MISMATCH;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void
|
||||
CPolicyCache::_CacheResult(
|
||||
const SHPOLICY_CONSTRAINT *pConstraint,
|
||||
PVOID pvValue,
|
||||
PDWORD pcbValue,
|
||||
PSHPOLICY_RESULT pResult)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pcbValue); // Reserved for future use
|
||||
|
||||
// Use caching only when dealing with DWORD value
|
||||
if (pConstraint->wFlags == SRRF_RT_DWORD)
|
||||
{
|
||||
pResult->dwValue = *(PDWORD)pvValue;
|
||||
pResult->state = POLICY_STATE_CACHED;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
CPolicyCache* g_pPolicyCache = NULL;
|
||||
CRITICAL_SECTION g_csPolicyLock;
|
||||
|
||||
// This function must be called under g_csPolicyLock
|
||||
static BOOL SHPolicyCache_Create(VOID)
|
||||
{
|
||||
if (g_pPolicyCache)
|
||||
return TRUE;
|
||||
|
||||
CPolicyCache *pCache = new CPolicyCache;
|
||||
if (!pCache)
|
||||
return FALSE;
|
||||
|
||||
if (!pCache->Initialize(g_PolicyItems, _countof(g_PolicyItems)))
|
||||
{
|
||||
delete pCache;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_pPolicyCache = pCache;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EXTERN_C VOID SHPolicyCache_DllProcessAttach(VOID)
|
||||
{
|
||||
InitializeCriticalSection(&g_csPolicyLock);
|
||||
}
|
||||
|
||||
EXTERN_C VOID SHPolicyCache_DllProcessDetach(VOID)
|
||||
{
|
||||
CPolicyCache* pCache;
|
||||
|
||||
EnterCriticalSection(&g_csPolicyLock);
|
||||
pCache = g_pPolicyCache;
|
||||
g_pPolicyCache = NULL;
|
||||
LeaveCriticalSection(&g_csPolicyLock);
|
||||
|
||||
delete pCache;
|
||||
DeleteCriticalSection(&g_csPolicyLock);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* SHWindowsPolicyGetValue (SHLWAPI.560)
|
||||
*
|
||||
* https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/winpolicy/getvalue.htm
|
||||
*/
|
||||
EXTERN_C
|
||||
HRESULT WINAPI
|
||||
SHWindowsPolicyGetValue(
|
||||
_In_ REFGUID rpolid,
|
||||
_Out_opt_ PVOID pvValue,
|
||||
_Out_opt_ PDWORD pcbValue)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
EnterCriticalSection(&g_csPolicyLock);
|
||||
if (SHPolicyCache_Create())
|
||||
hr = g_pPolicyCache->GetValue(rpolid, pvValue, pcbValue);
|
||||
LeaveCriticalSection(&g_csPolicyLock);
|
||||
return hr;
|
||||
}
|
||||
@@ -557,7 +557,7 @@
|
||||
557 stub -noname SHCoCreateExtension
|
||||
558 stub -noname SHCoExtensionCollectStats
|
||||
559 stub -noname SHGetSignatureInfo
|
||||
560 stdcall -stub -noname SHWindowsPolicyGetValue(ptr ptr ptr)
|
||||
560 stdcall -noname SHWindowsPolicyGetValue(ptr ptr ptr)
|
||||
561 stub -noname AssocGetUrlAction
|
||||
562 stub -noname SHGetPrivateProfileInt
|
||||
563 stdcall -stub -noname SHGetPrivateProfileSection(wstr ptr long ptr)
|
||||
|
||||
@@ -38,6 +38,8 @@ extern CRITICAL_SECTION g_csZoneMgrLock;
|
||||
extern CRITICAL_SECTION g_csBagCacheLock;
|
||||
VOID FreeViewStatePropertyBagCache(VOID);
|
||||
VOID SHLWAPI_DeleteCachedZonesManager(VOID);
|
||||
VOID SHPolicyCache_DllProcessAttach(VOID);
|
||||
VOID SHPolicyCache_DllProcessDetach(VOID);
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
@@ -72,6 +74,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
||||
#ifdef __REACTOS__
|
||||
InitializeCriticalSection(&g_csZoneMgrLock);
|
||||
InitializeCriticalSection(&g_csBagCacheLock);
|
||||
SHPolicyCache_DllProcessAttach();
|
||||
#endif
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
@@ -81,6 +84,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
||||
SHLWAPI_DeleteCachedZonesManager();
|
||||
DeleteCriticalSection(&g_csBagCacheLock);
|
||||
DeleteCriticalSection(&g_csZoneMgrLock);
|
||||
SHPolicyCache_DllProcessDetach();
|
||||
#endif
|
||||
if (SHLWAPI_ThreadRef_index != TLS_OUT_OF_INDEXES) TlsFree(SHLWAPI_ThreadRef_index);
|
||||
break;
|
||||
|
||||
@@ -203,6 +203,19 @@ DEFINE_GUID(IID_IDriveFolderExt, 0x3EC36F3E, 0x5BA3, 0x4C3D, 0xBF, 0x3
|
||||
DEFINE_GUID(IID_IPinnedListOld, 0xC3C6EB6D, 0xC837, 0x4EAE, 0xB1, 0x72, 0x5F, 0xEC, 0x52, 0xA2, 0xA4, 0xFD); /*version 6.0*/
|
||||
DEFINE_GUID(IID_IPinnedList, 0xBBD20037, 0xBC0E, 0x42F1, 0x91, 0x3F, 0xE2, 0x93, 0x6B, 0xB0, 0xEA, 0x0C); /*version 6.1*/
|
||||
|
||||
DEFINE_GUID(GUID_Restrictions, 0xA48F1A32, 0xA340, 0x11D1, 0xBC, 0x6B, 0x00, 0xA0, 0xC9, 0x03, 0x12, 0xE1);
|
||||
DEFINE_GUID(POLID_UsePathEnvVarForCommandTemplates, 0x1FF8F603, 0x056A, 0x4F52, 0x89, 0xCC, 0x82, 0xAD, 0x1C, 0xA1, 0xC1, 0x9A);
|
||||
DEFINE_GUID(POLID_ScanWithAntiVirus, 0xECF90404, 0xF38C, 0x44FE, 0x9F, 0x1B, 0x02, 0xA7, 0x2B, 0xAF, 0x60, 0x3C);
|
||||
DEFINE_GUID(POLID_SaveZoneInformation, 0xECF90405, 0xF38C, 0x44FE, 0x9F, 0x1B, 0x02, 0xA7, 0x2B, 0xAF, 0x60, 0x3C);
|
||||
DEFINE_GUID(POLID_UseTrustedHandlers, 0xECF90406, 0xF38C, 0x44FE, 0x9F, 0x1B, 0x02, 0xA7, 0x2B, 0xAF, 0x60, 0x3C);
|
||||
DEFINE_GUID(POLID_HideZoneInfoOnProperties, 0xECF90408, 0xF38C, 0x44FE, 0x9F, 0x1B, 0x02, 0xA7, 0x2B, 0xAF, 0x60, 0x3C);
|
||||
DEFINE_GUID(POLID_DefaultFileTypeRisk, 0xECF90409, 0xF38C, 0x44FE, 0x9F, 0x1B, 0x02, 0xA7, 0x2B, 0xAF, 0x60, 0x3C);
|
||||
DEFINE_GUID(POLID_HighRiskFileTypes, 0xECF9040A, 0xF38C, 0x44FE, 0x9F, 0x1B, 0x02, 0xA7, 0x2B, 0xAF, 0x60, 0x3C);
|
||||
DEFINE_GUID(POLID_ModRiskFileTypes, 0xECF9040B, 0xF38C, 0x44FE, 0x9F, 0x1B, 0x02, 0xA7, 0x2B, 0xAF, 0x60, 0x3C);
|
||||
DEFINE_GUID(POLID_LowRiskFileTypes, 0xECF9040C, 0xF38C, 0x44FE, 0x9F, 0x1B, 0x02, 0xA7, 0x2B, 0xAF, 0x60, 0x3C);
|
||||
DEFINE_GUID(POLID_PreXPSP2ShellProtocolBehavior, 0x4FC60822, 0x47AF, 0x4BEE, 0xA7, 0xDA, 0xC9, 0x9A, 0x6E, 0x8E, 0x5D, 0x8D);
|
||||
DEFINE_GUID(POLID_CompareJunctionness, 0xB3AB7D3B, 0x698F, 0x401E, 0xBF, 0x89, 0x30, 0x02, 0x33, 0x35, 0xA2, 0x67);
|
||||
|
||||
#define CGID_IExplorerToolbar IID_IExplorerToolbar
|
||||
#define SID_IExplorerToolbar IID_IExplorerToolbar
|
||||
#define SID_ITargetFrame2 IID_ITargetFrame2
|
||||
|
||||
@@ -497,6 +497,14 @@ PWSTR WINAPI CharLowerNoDBCSW(_Inout_ PWSTR lpString);
|
||||
PSTR WINAPI CharUpperNoDBCSA(_Inout_ PSTR lpString);
|
||||
PWSTR WINAPI CharUpperNoDBCSW(_Inout_ PWSTR lpString);
|
||||
|
||||
HRESULT WINAPI
|
||||
SHWindowsPolicyGetValue(
|
||||
_In_ REFGUID rpolid,
|
||||
_Out_opt_ PVOID pvValue,
|
||||
_Out_opt_ PDWORD pcbValue);
|
||||
|
||||
#define E_DATATYPE_MISMATCH HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH)
|
||||
|
||||
/*****************************************************************************
|
||||
* IAssociationElementOld interface
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user