1 /*
2 * shpolicy.c - Data for shell/system policies.
3 *
4 * Copyright 1999 Ian Schmidt <ischmidt@cfl.rr.com>
5 * Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 *
21 * NOTES:
22 *
23 * Some of these policies can be tweaked via the System Policy
24 * Editor which came with the Win95 Migration Guide, although
25 * there doesn't appear to be an updated Win98 version that
26 * would handle the many new policies introduced since then.
27 * You could easily write one with the information in
28 * this file...
29 */
30
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #define WIN32_NO_STATUS
36 #define _INC_WINDOWS
37
38 #include <windef.h>
39 #include <winbase.h>
40 #include <shlobj.h>
41 #include <initguid.h>
42 #include <shlwapi_undoc.h>
43 #include <wine/debug.h>
44
45 #include "shell32_main.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(shell);
48
49 DEFINE_GUID(GUID_Restrictions, 0xA48F1A32, 0xA340, 0x11D1, 0xBC, 0x6B, 0x00, 0xA0, 0xC9, 0x03, 0x12, 0xE1);
50
51 #define DEFINE_POLICY(policy, appstr, keystr) \
52 { policy, L##appstr, L##keystr }
53
54 static const POLICYDATA s_PolicyTable[] =
55 {
56 #include "PolicyData.h"
57 { 0, NULL, NULL }
58 };
59
60 #undef DEFINE_POLICY
61
62 /*
63 * The restriction-related variables
64 */
65 HANDLE g_hRestGlobalCounter = NULL;
66 LONG g_nRestCountValue = -1;
67 DWORD g_RestValues[_countof(s_PolicyTable)] = { 0 };
68
69 /****************************************************************************
70 * SHELL_GetCachedGlobalCounter
71 *
72 * Retrieves the global counter using cache in a thread-safe manner.
73 * If a cache of global counter exists, the function returns it.
74 * If there is no cache, the function creates a global counter.
75 *
76 * @param[in,out] phGlobalCounter The pointer to the handle of global counter.
77 * @param[in] rguid The GUID of global counter.
78 * @return The handle of the global counter.
79 * @implemented
80 */
81 #ifdef __REACTOS__
82 EXTERN_C HANDLE
83 #else
84 static HANDLE
85 #endif
SHELL_GetCachedGlobalCounter(_Inout_ HANDLE * phGlobalCounter,_In_ REFGUID rguid)86 SHELL_GetCachedGlobalCounter(_Inout_ HANDLE *phGlobalCounter, _In_ REFGUID rguid)
87 {
88 HANDLE hGlobalCounter;
89 if (*phGlobalCounter)
90 return *phGlobalCounter;
91 hGlobalCounter = SHGlobalCounterCreate(rguid);
92 if (InterlockedCompareExchangePointer(phGlobalCounter, hGlobalCounter, NULL))
93 CloseHandle(hGlobalCounter);
94 return *phGlobalCounter;
95 }
96
97 /****************************************************************************
98 * SHELL_GetRestrictionsCounter
99 *
100 * Retrieves the global counter for GUID_Restrictions using caching in a
101 * thread-safe manner. The variable g_hRestGlobalCounter is used for caching.
102 *
103 * @return The handle of the global counter.
104 * @see SHELL_GetCachedGlobalCounter
105 * @implemented
106 */
SHELL_GetRestrictionsCounter(VOID)107 static HANDLE SHELL_GetRestrictionsCounter(VOID)
108 {
109 return SHELL_GetCachedGlobalCounter(&g_hRestGlobalCounter, &GUID_Restrictions);
110 }
111
112 /****************************************************************************
113 * SHELL_QueryRestrictionsChanged
114 *
115 * @return The value of the global counter for GUID_Restrictions.
116 * @see SHELL_GetRestrictionsCounter
117 * @implemented
118 */
SHELL_QueryRestrictionsChanged(VOID)119 static BOOL SHELL_QueryRestrictionsChanged(VOID)
120 {
121 LONG Value = SHGlobalCounterGetValue(SHELL_GetRestrictionsCounter());
122 if (g_nRestCountValue == Value)
123 return FALSE;
124
125 g_nRestCountValue = Value;
126 return TRUE;
127 }
128
129 /*************************************************************************
130 * SHRestricted [SHELL32.100]
131 *
132 * Get the value associated with a policy Id.
133 *
134 * PARAMS
135 * pol [I] Policy Id
136 *
137 * RETURNS
138 * The queried value for the policy.
139 *
140 * NOTES
141 * Exported by ordinal.
142 * This function caches the retrieved values to prevent unnecessary registry access,
143 * if SHSettingsChanged() was previously called.
144 *
145 * REFERENCES
146 * a: MS System Policy Editor.
147 * b: 98Lite 2.0 (which uses many of these policy keys) http://www.98lite.net/
148 * c: 'The Windows 95 Registry', by John Woram, 1996 MIS: Press
149 */
SHRestricted(RESTRICTIONS rest)150 DWORD WINAPI SHRestricted (RESTRICTIONS rest)
151 {
152 TRACE("(0x%08lX)\n", rest);
153
154 /* If restrictions from registry have changed, reset all cached values to SHELL_NO_POLICY */
155 if (SHELL_QueryRestrictionsChanged())
156 FillMemory(&g_RestValues, sizeof(g_RestValues), 0xFF);
157
158 return SHRestrictionLookup(rest, NULL, s_PolicyTable, g_RestValues);
159 }
160
161 /*************************************************************************
162 * SHSettingsChanged [SHELL32.244]
163 *
164 * Initialise the policy cache to speed up calls to SHRestricted().
165 *
166 * PARAMS
167 * unused [I] Reserved.
168 * pszKey [I] Registry key to scan.
169 *
170 * RETURNS
171 * Success: -1. The policy cache is initialised.
172 * Failure: 0, if inpRegKey is any value other than NULL, "Policy", or
173 * "Software\Microsoft\Windows\CurrentVersion\Policies".
174 *
175 * NOTES
176 * Exported by ordinal. Introduced in Win98.
177 */
SHSettingsChanged(LPCVOID unused,LPCWSTR pszKey)178 BOOL WINAPI SHSettingsChanged(LPCVOID unused, LPCWSTR pszKey)
179 {
180 TRACE("(%p, %s)\n", unused, debugstr_w(pszKey));
181
182 if (pszKey &&
183 lstrcmpiW(L"Policy", pszKey) != 0 &&
184 lstrcmpiW(L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies", pszKey) != 0)
185 {
186 return FALSE;
187 }
188
189 return SHGlobalCounterIncrement(SHELL_GetRestrictionsCounter());
190 }
191