ReactOS 0.4.17-dev-301-g9127a53
policy.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS shlwapi
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: Implement SHWindowsPolicyGetValue
5 * COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6 */
7
8#define _ATL_NO_EXCEPTIONS
9#include <windef.h>
10#include <shlobj.h>
11#include <shlwapi.h>
12#include <shlwapi_undoc.h>
13#include <shlguid_undoc.h>
14#include <atlstr.h>
15#include <strsafe.h>
16#include <new>
17#include <wine/debug.h>
18
20
21typedef enum tagPOLICY_STATE
22{
23 POLICY_STATE_UNCACHED = 0, // Uncached
24 POLICY_STATE_NOT_FOUND = 1, // Not found
25 POLICY_STATE_CACHED = 2, // Cached
27
28// Result
29typedef struct tagSHPOLICY_RESULT
30{
34
35// Constraints
37{
43
44static const SHPOLICY_CONSTRAINT c_Bool = { SRRF_RT_DWORD, sizeof(DWORD), 0, 1 };
45static const SHPOLICY_CONSTRAINT c_String = { SRRF_RT_REG_SZ, sizeof(WCHAR), 0, 0 };
46static const SHPOLICY_CONSTRAINT c_TriValue = { SRRF_RT_DWORD, sizeof(DWORD), 1, 3 };
47static const SHPOLICY_CONSTRAINT c_Special = { SRRF_RT_DWORD, sizeof(DWORD), 0x1806, 0x1808 };
48
49// Items
50typedef struct tagSHPOLICY_ITEM
51{
52 REFGUID rpolid; // POLID (policy descriptor)
57
59{
60 { POLID_UsePathEnvVarForCommandTemplates, L"Explorer", L"UsePathEnvVarForCommandTemplates",
61 &c_Bool },
62 { POLID_ScanWithAntiVirus, L"Attachments", L"ScanWithAntiVirus", &c_TriValue },
63 { POLID_SaveZoneInformation, L"Attachments", L"SaveZoneInformation", &c_TriValue },
64 { POLID_UseTrustedHandlers, L"Attachments", L"UseTrustedHandlers", &c_TriValue },
65 { POLID_HideZoneInfoOnProperties, L"Attachments", L"HideZoneInfoOnProperties", &c_Bool },
66 { POLID_DefaultFileTypeRisk, L"Associations", L"DefaultFileTypeRisk", &c_Special },
67 { POLID_HighRiskFileTypes, L"Associations", L"HighRiskFileTypes", &c_String },
68 { POLID_ModRiskFileTypes, L"Associations", L"ModRiskFileTypes", &c_String },
69 { POLID_LowRiskFileTypes, L"Associations", L"LowRiskFileTypes", &c_String },
70 { POLID_PreXPSP2ShellProtocolBehavior, L"Explorer", L"PreXPSP2ShellProtocolBehavior", &c_Bool },
71 { POLID_CompareJunctionness, L"Explorer", L"CompareJunctionness", &c_Bool },
72};
73
74/**************************************************************************
75 * CPolicyCache
76 */
78{
79public:
81 {
83
86 }
87
89 {
91 m_pszRootKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies";
93 m_cItems = cItems;
95 if (!m_pResults)
96 return FALSE;
97 m_hGlobalCounter = SHGlobalCounterCreate(GUID_Restrictions);
99 {
102 return FALSE;
103 }
104 return TRUE;
105 }
106
107 HRESULT GetValue(_In_ REFGUID rpolid, _Out_opt_ PVOID pvValue, _Out_opt_ PDWORD pcbValue);
108
109protected:
116
118 {
120 if (m_nCounterValue != Value)
121 {
124 }
125 }
126
129 _In_ LPCWSTR pszValueName,
130 _In_ const SHPOLICY_CONSTRAINT* pConstraint,
134
135 static void _CacheResult(
136 const SHPOLICY_CONSTRAINT *pConstraint,
137 PVOID pvValue,
138 PDWORD pcbValue,
139 PSHPOLICY_RESULT pResult);
140};
141
144{
146
147 if (m_cItems == 0)
148 return E_UNEXPECTED;
149
150 UINT iItem;
151 for (iItem = 0; iItem < m_cItems; ++iItem)
152 {
153 if (IsEqualGUID(m_pItems[iItem].rpolid, rpolid))
154 break;
155 }
156
157 if (iItem >= m_cItems)
158 return E_UNEXPECTED;
159
160 const SHPOLICY_ITEM *pItem = &m_pItems[iItem];
161 PSHPOLICY_RESULT pResult = &m_pResults[iItem];
162
163 if (pResult->state == POLICY_STATE_NOT_FOUND)
165
166 // Use caching only when dealing with DWORD value
167 if (pvValue && pcbValue && *pcbValue == sizeof(DWORD) && pResult->state == POLICY_STATE_CACHED)
168 {
169 *(PDWORD)pvValue = pResult->dwValue;
170 return S_OK;
171 }
172
173 HRESULT hr = _GetValue(pItem->pszKeyName, pItem->pszValueName, pItem->pConstraint, NULL,
174 pvValue, pcbValue);
176 pResult->state = POLICY_STATE_NOT_FOUND;
177 else if (SUCCEEDED(hr) && pvValue)
178 _CacheResult(pItem->pConstraint, pvValue, pcbValue, pResult);
179
180 return hr;
181}
182
185 _In_ LPCWSTR pszValueName,
186 _In_ const SHPOLICY_CONSTRAINT* pConstraint,
190{
191 CStringW szFullKey = CStringW(m_pszRootKey) + L"\\" + pszSubKey;
192
193 DWORD cbDataSaved = pcbData ? *pcbData : 0;
194 WORD wFlags = pConstraint->wFlags;
195
196 LSTATUS error = RegGetValueW(HKEY_LOCAL_MACHINE, szFullKey, pszValueName, wFlags, pdwType,
197 pvData, pcbData);
199 {
200 if (pcbData)
201 *pcbData = cbDataSaved;
202 error = RegGetValueW(HKEY_CURRENT_USER, szFullKey, pszValueName, wFlags, pdwType,
203 pvData, pcbData);
204 }
205
206 if (error)
208
209 if (!pvData)
210 return S_OK;
211
212 if (pConstraint->wFlags == SRRF_RT_DWORD && pConstraint->wMinSize == sizeof(DWORD))
213 {
214 DWORD dwValue = *(PDWORD)pvData;
215 if (dwValue < pConstraint->dwMin || pConstraint->dwMax < dwValue)
216 return E_DATATYPE_MISMATCH;
217 }
218
219 return S_OK;
220}
221
222void
224 const SHPOLICY_CONSTRAINT *pConstraint,
225 PVOID pvValue,
226 PDWORD pcbValue,
227 PSHPOLICY_RESULT pResult)
228{
229 UNREFERENCED_PARAMETER(pcbValue); // Reserved for future use
230
231 // Use caching only when dealing with DWORD value
232 if (pConstraint->wFlags == SRRF_RT_DWORD)
233 {
234 pResult->dwValue = *(PDWORD)pvValue;
235 pResult->state = POLICY_STATE_CACHED;
236 }
237}
238
239/***************************************************************************/
240
243
244// This function must be called under g_csPolicyLock
246{
247 if (g_pPolicyCache)
248 return TRUE;
249
250 CPolicyCache* pCache = new(std::nothrow) CPolicyCache;
251 if (!pCache)
252 return FALSE;
253
255 {
256 delete pCache;
257 return FALSE;
258 }
259
260 g_pPolicyCache = pCache;
261 return TRUE;
262}
263
265{
267}
268
270{
271 CPolicyCache* pCache;
272
274 pCache = g_pPolicyCache;
277
278 delete pCache;
280}
281
282/**************************************************************************
283 * SHWindowsPolicyGetValue (SHLWAPI.560)
284 *
285 * https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/winpolicy/getvalue.htm
286 */
290 _In_ REFGUID rpolid,
291 _Out_opt_ PVOID pvValue,
292 _Out_opt_ PDWORD pcbValue)
293{
294 HRESULT hr = E_FAIL;
295
298 hr = g_pPolicyCache->GetValue(rpolid, pvValue, pcbValue);
300 return hr;
301}
WINBASEAPI _Check_return_ _Out_ AppPolicyProcessTerminationMethod * policy
Definition: appmodel.h:73
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define EXTERN_C
Definition: basetyps.h:12
HRESULT GetValue(_In_ REFGUID rpolid, _Out_opt_ PVOID pvValue, _Out_opt_ PDWORD pcbValue)
Definition: policy.cpp:143
void _ValidateCachedResults()
Definition: policy.cpp:117
HANDLE m_hGlobalCounter
Definition: policy.cpp:111
~CPolicyCache()
Definition: policy.cpp:80
const SHPOLICY_ITEM * m_pItems
Definition: policy.cpp:114
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)
Definition: policy.cpp:183
BOOL Initialize(const SHPOLICY_ITEM *pItems, UINT cItems)
Definition: policy.cpp:88
DWORD m_cItems
Definition: policy.cpp:113
LPCWSTR m_pszRootKey
Definition: policy.cpp:110
PSHPOLICY_RESULT m_pResults
Definition: policy.cpp:115
LONG m_nCounterValue
Definition: policy.cpp:112
static void _CacheResult(const SHPOLICY_CONSTRAINT *pConstraint, PVOID pvValue, PDWORD pcbValue, PSHPOLICY_RESULT pResult)
Definition: policy.cpp:223
#define E_FAIL
Definition: ddrawi.h:102
HRESULT hr
Definition: delayimp.cpp:582
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LSTATUS WINAPI RegGetValueW(HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: reg.c:1931
#define CloseHandle
Definition: compat.h:739
HANDLE WINAPI SHGlobalCounterCreate(REFGUID guid)
Definition: thread.c:551
LONG WINAPI SHGlobalCounterGetValue(HANDLE hSem)
Definition: thread.c:432
#define L(x)
Definition: resources.c:13
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define ZeroMemory
Definition: minwinbase.h:31
#define LPTR
Definition: minwinbase.h:93
#define error(str)
Definition: mkdosfs.c:1605
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static int int const SCRIPT_CONTROL const SCRIPT_STATE SCRIPT_ITEM * pItems
Definition: usp10.c:62
CAtlStringW CStringW
Definition: atlstr.h:130
unsigned int UINT
Definition: ndis.h:50
_In_ LPWSTR _In_ DWORD _In_ LPCVOID pvData
Definition: netsh.h:116
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_opt_
Definition: no_sal2.h:216
#define _In_
Definition: no_sal2.h:158
#define DWORD
Definition: nt_native.h:44
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
short WCHAR
Definition: pedump.c:58
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
struct tagSHPOLICY_CONSTRAINT * PSHPOLICY_CONSTRAINT
enum tagPOLICY_STATE POLICY_STATE
static const SHPOLICY_CONSTRAINT c_String
Definition: policy.cpp:45
static BOOL SHPolicyCache_Create(VOID)
Definition: policy.cpp:245
struct tagSHPOLICY_CONSTRAINT SHPOLICY_CONSTRAINT
static const SHPOLICY_CONSTRAINT c_Special
Definition: policy.cpp:47
EXTERN_C VOID SHPolicyCache_DllProcessAttach(VOID)
Definition: policy.cpp:264
struct tagSHPOLICY_ITEM * PSHPOLICY_ITEM
tagPOLICY_STATE
Definition: policy.cpp:22
@ POLICY_STATE_UNCACHED
Definition: policy.cpp:23
@ POLICY_STATE_CACHED
Definition: policy.cpp:25
@ POLICY_STATE_NOT_FOUND
Definition: policy.cpp:24
EXTERN_C VOID SHPolicyCache_DllProcessDetach(VOID)
Definition: policy.cpp:269
EXTERN_C HRESULT WINAPI SHWindowsPolicyGetValue(_In_ REFGUID rpolid, _Out_opt_ PVOID pvValue, _Out_opt_ PDWORD pcbValue)
Definition: policy.cpp:289
struct tagSHPOLICY_RESULT SHPOLICY_RESULT
CPolicyCache * g_pPolicyCache
Definition: policy.cpp:241
struct tagSHPOLICY_ITEM SHPOLICY_ITEM
struct tagSHPOLICY_RESULT * PSHPOLICY_RESULT
static const SHPOLICY_ITEM g_PolicyItems[]
Definition: policy.cpp:58
static const SHPOLICY_CONSTRAINT c_TriValue
Definition: policy.cpp:46
CRITICAL_SECTION g_csPolicyLock
Definition: policy.cpp:242
static const SHPOLICY_CONSTRAINT c_Bool
Definition: policy.cpp:44
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
_In_opt_ LPCSTR _In_opt_ LPCSTR _In_ SRRF _Out_opt_ LPDWORD pdwType
Definition: shlwapi.h:783
_In_ _Out_writes_opt_ pcchValueName _Inout_opt_ LPDWORD _Out_opt_ _Out_writes_bytes_to_opt_ pcbData _Inout_opt_ LPDWORD pcbData
Definition: shlwapi.h:757
_In_opt_ LPCSTR pszSubKey
Definition: shlwapi.h:783
#define SRRF_RT_REG_SZ
Definition: shlwapi.h:698
#define SRRF_RT_DWORD
Definition: shlwapi.h:705
#define E_DATATYPE_MISMATCH
#define _countof(array)
Definition: sndvol32.h:70
Definition: scsiwmi.h:51
PCWSTR pszValueName
Definition: policy.cpp:54
const SHPOLICY_CONSTRAINT * pConstraint
Definition: policy.cpp:55
PCWSTR pszKeyName
Definition: policy.cpp:53
REFGUID rpolid
Definition: policy.cpp:52
POLICY_STATE state
Definition: policy.cpp:31
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:687
const uint16_t * PCWSTR
Definition: typedefs.h:57
const uint16_t * LPCWSTR
Definition: typedefs.h:57
#define MINLONG
Definition: umtypes.h:115
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
WINBASEAPI _In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon_undoc.h:337
#define WINAPI
Definition: msvc.h:6
static HRESULT HRESULT_FROM_WIN32(unsigned int x)
Definition: winerror.h:210
#define E_UNEXPECTED
Definition: winerror.h:3528
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11