ReactOS 0.4.17-dev-218-g5635d24
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 <wine/debug.h>
17
19
20typedef enum tagPOLICY_STATE
21{
22 POLICY_STATE_UNCACHED = 0, // Uncached
23 POLICY_STATE_NOT_FOUND = 1, // Not found
24 POLICY_STATE_CACHED = 2, // Cached
26
27// Result
28typedef struct tagSHPOLICY_RESULT
29{
33
34// Constraints
36{
42
43static const SHPOLICY_CONSTRAINT c_Bool = { SRRF_RT_DWORD, sizeof(DWORD), 0, 1 };
44static const SHPOLICY_CONSTRAINT c_String = { SRRF_RT_REG_SZ, sizeof(WCHAR), 0, 0 };
45static const SHPOLICY_CONSTRAINT c_TriValue = { SRRF_RT_DWORD, sizeof(DWORD), 1, 3 };
46static const SHPOLICY_CONSTRAINT c_Special = { SRRF_RT_DWORD, sizeof(DWORD), 0x1806, 0x1808 };
47
48// Items
49typedef struct tagSHPOLICY_ITEM
50{
51 REFGUID rpolid; // POLID (policy descriptor)
56
58{
59 { POLID_UsePathEnvVarForCommandTemplates, L"Explorer", L"UsePathEnvVarForCommandTemplates",
60 &c_Bool },
61 { POLID_ScanWithAntiVirus, L"Attachments", L"ScanWithAntiVirus", &c_TriValue },
62 { POLID_SaveZoneInformation, L"Attachments", L"SaveZoneInformation", &c_TriValue },
63 { POLID_UseTrustedHandlers, L"Attachments", L"UseTrustedHandlers", &c_TriValue },
64 { POLID_HideZoneInfoOnProperties, L"Attachments", L"HideZoneInfoOnProperties", &c_Bool },
65 { POLID_DefaultFileTypeRisk, L"Associations", L"DefaultFileTypeRisk", &c_Special },
66 { POLID_HighRiskFileTypes, L"Associations", L"HighRiskFileTypes", &c_String },
67 { POLID_ModRiskFileTypes, L"Associations", L"ModRiskFileTypes", &c_String },
68 { POLID_LowRiskFileTypes, L"Associations", L"LowRiskFileTypes", &c_String },
69 { POLID_PreXPSP2ShellProtocolBehavior, L"Explorer", L"PreXPSP2ShellProtocolBehavior", &c_Bool },
70 { POLID_CompareJunctionness, L"Explorer", L"CompareJunctionness", &c_Bool },
71};
72
73/**************************************************************************
74 * CPolicyCache
75 */
77{
78public:
80 {
82
85 }
86
87 static void* operator new(size_t size)
88 {
89 // Returns NULL on failure; caller must check before use.
90 // NOTE: C++ UB if constructor runs on NULL, but ReactOS convention.
91 return LocalAlloc(LPTR, size);
92 }
93 static void operator delete(void *ptr)
94 {
96 }
97
99 {
101 m_pszRootKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies";
103 m_cItems = cItems;
105 if (!m_pResults)
106 return FALSE;
107 m_hGlobalCounter = SHGlobalCounterCreate(GUID_Restrictions);
108 if (!m_hGlobalCounter)
109 {
112 return FALSE;
113 }
114 return TRUE;
115 }
116
117 HRESULT GetValue(_In_ REFGUID rpolid, _Out_opt_ PVOID pvValue, _Out_opt_ PDWORD pcbValue);
118
119protected:
126
128 {
130 if (m_nCounterValue != Value)
131 {
134 }
135 }
136
139 _In_ LPCWSTR pszValueName,
140 _In_ const SHPOLICY_CONSTRAINT* pConstraint,
144
145 static void _CacheResult(
146 const SHPOLICY_CONSTRAINT *pConstraint,
147 PVOID pvValue,
148 PDWORD pcbValue,
149 PSHPOLICY_RESULT pResult);
150};
151
154{
156
157 if (m_cItems == 0)
158 return E_UNEXPECTED;
159
160 UINT iItem;
161 for (iItem = 0; iItem < m_cItems; ++iItem)
162 {
163 if (IsEqualGUID(m_pItems[iItem].rpolid, rpolid))
164 break;
165 }
166
167 if (iItem >= m_cItems)
168 return E_UNEXPECTED;
169
170 const SHPOLICY_ITEM *pItem = &m_pItems[iItem];
171 PSHPOLICY_RESULT pResult = &m_pResults[iItem];
172
173 if (pResult->state == POLICY_STATE_NOT_FOUND)
175
176 // Use caching only when dealing with DWORD value
177 if (pvValue && pcbValue && *pcbValue == sizeof(DWORD) && pResult->state == POLICY_STATE_CACHED)
178 {
179 *(PDWORD)pvValue = pResult->dwValue;
180 return S_OK;
181 }
182
183 HRESULT hr = _GetValue(pItem->pszKeyName, pItem->pszValueName, pItem->pConstraint, NULL,
184 pvValue, pcbValue);
186 pResult->state = POLICY_STATE_NOT_FOUND;
187 else if (SUCCEEDED(hr) && pvValue)
188 _CacheResult(pItem->pConstraint, pvValue, pcbValue, pResult);
189
190 return hr;
191}
192
195 _In_ LPCWSTR pszValueName,
196 _In_ const SHPOLICY_CONSTRAINT* pConstraint,
200{
201 CStringW szFullKey = CStringW(m_pszRootKey) + L"\\" + pszSubKey;
202
203 DWORD cbDataSaved = pcbData ? *pcbData : 0;
204 WORD wFlags = pConstraint->wFlags;
205
206 LSTATUS error = RegGetValueW(HKEY_LOCAL_MACHINE, szFullKey, pszValueName, wFlags, pdwType,
207 pvData, pcbData);
209 {
210 if (pcbData)
211 *pcbData = cbDataSaved;
212 error = RegGetValueW(HKEY_CURRENT_USER, szFullKey, pszValueName, wFlags, pdwType,
213 pvData, pcbData);
214 }
215
216 if (error)
218
219 if (!pvData)
220 return S_OK;
221
222 if (pConstraint->wFlags == SRRF_RT_DWORD && pConstraint->wMinSize == sizeof(DWORD))
223 {
224 DWORD dwValue = *(PDWORD)pvData;
225 if (dwValue < pConstraint->dwMin || pConstraint->dwMax < dwValue)
226 return E_DATATYPE_MISMATCH;
227 }
228
229 return S_OK;
230}
231
232void
234 const SHPOLICY_CONSTRAINT *pConstraint,
235 PVOID pvValue,
236 PDWORD pcbValue,
237 PSHPOLICY_RESULT pResult)
238{
239 UNREFERENCED_PARAMETER(pcbValue); // Reserved for future use
240
241 // Use caching only when dealing with DWORD value
242 if (pConstraint->wFlags == SRRF_RT_DWORD)
243 {
244 pResult->dwValue = *(PDWORD)pvValue;
245 pResult->state = POLICY_STATE_CACHED;
246 }
247}
248
249/***************************************************************************/
250
253
254// This function must be called under g_csPolicyLock
256{
257 if (g_pPolicyCache)
258 return TRUE;
259
260 CPolicyCache *pCache = new CPolicyCache;
261 if (!pCache)
262 return FALSE;
263
265 {
266 delete pCache;
267 return FALSE;
268 }
269
270 g_pPolicyCache = pCache;
271 return TRUE;
272}
273
275{
277}
278
280{
281 CPolicyCache* pCache;
282
284 pCache = g_pPolicyCache;
287
288 delete pCache;
290}
291
292/**************************************************************************
293 * SHWindowsPolicyGetValue (SHLWAPI.560)
294 *
295 * https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/winpolicy/getvalue.htm
296 */
300 _In_ REFGUID rpolid,
301 _Out_opt_ PVOID pvValue,
302 _Out_opt_ PDWORD pcbValue)
303{
304 HRESULT hr = E_FAIL;
305
308 hr = g_pPolicyCache->GetValue(rpolid, pvValue, pcbValue);
310 return hr;
311}
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:153
void _ValidateCachedResults()
Definition: policy.cpp:127
HANDLE m_hGlobalCounter
Definition: policy.cpp:121
~CPolicyCache()
Definition: policy.cpp:79
const SHPOLICY_ITEM * m_pItems
Definition: policy.cpp:124
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:193
BOOL Initialize(const SHPOLICY_ITEM *pItems, UINT cItems)
Definition: policy.cpp:98
DWORD m_cItems
Definition: policy.cpp:123
LPCWSTR m_pszRootKey
Definition: policy.cpp:120
PSHPOLICY_RESULT m_pResults
Definition: policy.cpp:125
LONG m_nCounterValue
Definition: policy.cpp:122
static void _CacheResult(const SHPOLICY_CONSTRAINT *pConstraint, PVOID pvValue, PDWORD pcbValue, PSHPOLICY_RESULT pResult)
Definition: policy.cpp:233
#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
GLsizeiptr size
Definition: glext.h:5919
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 PVOID ptr
Definition: dispmode.c:27
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:44
static BOOL SHPolicyCache_Create(VOID)
Definition: policy.cpp:255
struct tagSHPOLICY_CONSTRAINT SHPOLICY_CONSTRAINT
static const SHPOLICY_CONSTRAINT c_Special
Definition: policy.cpp:46
EXTERN_C VOID SHPolicyCache_DllProcessAttach(VOID)
Definition: policy.cpp:274
struct tagSHPOLICY_ITEM * PSHPOLICY_ITEM
tagPOLICY_STATE
Definition: policy.cpp:21
@ POLICY_STATE_UNCACHED
Definition: policy.cpp:22
@ POLICY_STATE_CACHED
Definition: policy.cpp:24
@ POLICY_STATE_NOT_FOUND
Definition: policy.cpp:23
EXTERN_C VOID SHPolicyCache_DllProcessDetach(VOID)
Definition: policy.cpp:279
EXTERN_C HRESULT WINAPI SHWindowsPolicyGetValue(_In_ REFGUID rpolid, _Out_opt_ PVOID pvValue, _Out_opt_ PDWORD pcbValue)
Definition: policy.cpp:299
struct tagSHPOLICY_RESULT SHPOLICY_RESULT
CPolicyCache * g_pPolicyCache
Definition: policy.cpp:251
struct tagSHPOLICY_ITEM SHPOLICY_ITEM
struct tagSHPOLICY_RESULT * PSHPOLICY_RESULT
static const SHPOLICY_ITEM g_PolicyItems[]
Definition: policy.cpp:57
static const SHPOLICY_CONSTRAINT c_TriValue
Definition: policy.cpp:45
CRITICAL_SECTION g_csPolicyLock
Definition: policy.cpp:252
static const SHPOLICY_CONSTRAINT c_Bool
Definition: policy.cpp:43
#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:53
const SHPOLICY_CONSTRAINT * pConstraint
Definition: policy.cpp:54
PCWSTR pszKeyName
Definition: policy.cpp:52
REFGUID rpolid
Definition: policy.cpp:51
POLICY_STATE state
Definition: policy.cpp:30
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