[GFLAGS] Move code around to handle multiple options
[reactos.git] / modules / rosapps / applications / cmdutils / gflags / pageheap.c
1 /*
2 * PROJECT: Global Flags utility
3 * LICENSE: GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
4 * PURPOSE: Global Flags utility page heap options
5 * COPYRIGHT: Copyright 2017 Pierre Schweitzer (pierre@reactos.org)
6 */
7
8 #include "gflags.h"
9
10 static BOOL Set = FALSE;
11 static BOOL Unset = FALSE;
12 static BOOL Full = FALSE;
13 static PWSTR Image = NULL;
14 static WCHAR ImageExecOptionsString[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options";
15
16
17 static VOID ModifyStatus(VOID)
18 {
19 LONG Ret;
20 DWORD MaxLen, GlobalFlags;
21 PVOID Buffer;
22 HKEY HandleKey, HandleSubKey;
23
24 Ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ImageExecOptionsString, 0, KEY_WRITE | KEY_READ, &HandleKey);
25 if (Ret != ERROR_SUCCESS)
26 {
27 wprintf(L"MS: RegOpenKeyEx failed (%d)\n", Ret);
28 return;
29 }
30
31 Ret = RegCreateKeyEx(HandleKey, Image, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &HandleSubKey, NULL);
32 if (Ret != ERROR_SUCCESS)
33 {
34 wprintf(L"MS: RegCreateKeyEx failed (%d)\n", Ret);
35 return;
36 }
37
38 Ret = RegQueryInfoKey(HandleSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL);
39 if (Ret != ERROR_SUCCESS)
40 {
41 wprintf(L"MS: RegQueryInfoKey failed (%d)\n", Ret);
42 RegCloseKey(HandleSubKey);
43 RegCloseKey(HandleKey);
44 return;
45 }
46
47 MaxLen = max(MaxLen, 11 * sizeof(WCHAR));
48 Buffer = HeapAlloc(GetProcessHeap(), 0, MaxLen);
49 if (Buffer == NULL)
50 {
51 wprintf(L"MS: HeapAlloc failed\n");
52 RegCloseKey(HandleSubKey);
53 RegCloseKey(HandleKey);
54 return;
55 }
56
57 GlobalFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"GlobalFlag", MaxLen);
58 if (Set)
59 {
60 GlobalFlags |= 0x02000000;
61 }
62 else
63 {
64 GlobalFlags &= ~0x02000000;
65 }
66
67 if (GlobalFlags != 0)
68 {
69 wsprintf(Buffer, L"0x%08x", GlobalFlags);
70 Ret = RegSetValueEx(HandleSubKey, L"GlobalFlag", 0, REG_SZ, Buffer, 11 * sizeof(WCHAR));
71 if (Ret != ERROR_SUCCESS)
72 {
73 wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret);
74 }
75 }
76 else
77 {
78 Ret = RegDeleteValue(HandleSubKey, L"GlobalFlag");
79 if (Ret != ERROR_SUCCESS)
80 {
81 wprintf(L"MS: RegDeleteValue failed (%d)\n", Ret);
82 }
83 }
84
85 if (Unset)
86 {
87 Ret = RegDeleteValue(HandleSubKey, L"PageHeapFlags");
88 if (Ret != ERROR_SUCCESS)
89 {
90 wprintf(L"MS: RegDeleteValue failed (%d)\n", Ret);
91 }
92 }
93 else
94 {
95 DWORD PageHeapFlags;
96
97 PageHeapFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"PageHeapFlags", MaxLen);
98 PageHeapFlags &= ~3;
99
100 if (Full)
101 {
102 PageHeapFlags |= 1;
103 }
104 PageHeapFlags |= 2;
105
106 wsprintf(Buffer, L"0x%x", PageHeapFlags);
107 Ret = RegSetValueEx(HandleSubKey, L"PageHeapFlags", 0, REG_SZ, Buffer, 11 * sizeof(WCHAR));
108 if (Ret != ERROR_SUCCESS)
109 {
110 wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret);
111 }
112 }
113
114 if (Set)
115 {
116 DWORD Type, VerifierFlags, Len;
117
118 VerifierFlags = 0;
119 Len = MaxLen;
120 if (RegQueryValueEx(HandleSubKey, L"VerifierFlags", NULL, &Type, Buffer, &Len) == ERROR_SUCCESS &&
121 Type == REG_DWORD && Len == sizeof(DWORD))
122 {
123 VerifierFlags = ((DWORD *)Buffer)[0];
124 VerifierFlags &= ~0x8001;
125 }
126
127 if (Full)
128 {
129 VerifierFlags |= 1;
130 }
131 else
132 {
133 VerifierFlags |= 0x8000;
134 }
135
136 Ret = RegSetValueEx(HandleSubKey, L"VerifierFlags", 0, REG_DWORD, (const BYTE *)&VerifierFlags, sizeof(DWORD));
137 if (Ret != ERROR_SUCCESS)
138 {
139 wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret);
140 }
141 }
142
143 wprintf(L"path: %s\n", ImageExecOptionsString);
144 wprintf(L"\t%s: page heap %s\n", Image, (Set ? L"enabled" : L"disabled"));
145
146 HeapFree(GetProcessHeap(), 0, Buffer);
147 RegCloseKey(HandleSubKey);
148 RegCloseKey(HandleKey);
149 }
150
151 static BOOL DisplayImageInfo(HKEY HandleKey, PWSTR SubKey, PBOOL Header)
152 {
153 LONG Ret;
154 BOOL Handled;
155 DWORD MaxLen, GlobalFlags;
156 HKEY HandleSubKey;
157 PVOID Buffer;
158
159 Ret = RegOpenKeyEx(HandleKey, SubKey, 0, KEY_READ, &HandleSubKey);
160 if (Ret != ERROR_SUCCESS)
161 {
162 wprintf(L"DII: RegOpenKeyEx failed (%d)\n", Ret);
163 return FALSE;
164 }
165
166 Ret = RegQueryInfoKey(HandleSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL);
167 if (Ret != ERROR_SUCCESS)
168 {
169 wprintf(L"DII: RegQueryInfoKey failed (%d)\n", Ret);
170 RegCloseKey(HandleSubKey);
171 return FALSE;
172 }
173
174 Buffer = HeapAlloc(GetProcessHeap(), 0, MaxLen);
175 if (Buffer == NULL)
176 {
177 wprintf(L"DII: HeapAlloc failed\n");
178 RegCloseKey(HandleSubKey);
179 return FALSE;
180 }
181
182 Handled = FALSE;
183 GlobalFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"GlobalFlag", MaxLen);
184 if (GlobalFlags & 0x02000000)
185 {
186 DWORD PageHeapFlags;
187
188 if (Image == NULL)
189 {
190 if (!*Header)
191 {
192 wprintf(L"path: %s\n", ImageExecOptionsString);
193 *Header = TRUE;
194 }
195 wprintf(L"\t%s: page heap enabled with flags (", SubKey);
196 }
197 else
198 {
199 wprintf(L"Page heap is enabled for %s with flags (", SubKey);
200 }
201
202 PageHeapFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"PageHeapFlags", MaxLen);
203 if (PageHeapFlags & 0x1)
204 {
205 wprintf(L"full ");
206 }
207
208 if (PageHeapFlags & 0x2)
209 {
210 wprintf(L"traces");
211 }
212
213 wprintf(L")\n");
214
215 Handled = TRUE;
216 }
217
218 HeapFree(GetProcessHeap(), 0, Buffer);
219 RegCloseKey(HandleSubKey);
220
221 return Handled;
222 }
223
224 static VOID DisplayStatus(VOID)
225 {
226 LONG Ret;
227 HKEY HandleKey;
228 DWORD Index, MaxLen, Handled;
229 TCHAR * SubKey;
230 BOOL Header;
231
232 Ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ImageExecOptionsString, 0, KEY_READ, &HandleKey);
233 if (Ret != ERROR_SUCCESS)
234 {
235 wprintf(L"DS: RegOpenKeyEx failed (%d)\n", Ret);
236 return;
237 }
238
239 Ret = RegQueryInfoKey(HandleKey, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL, NULL, NULL, NULL, NULL);
240 if (Ret != ERROR_SUCCESS)
241 {
242 wprintf(L"DS: RegQueryInfoKey failed (%d)\n", Ret);
243 RegCloseKey(HandleKey);
244 return;
245 }
246
247 ++MaxLen; // NULL-char
248 SubKey = HeapAlloc(GetProcessHeap(), 0, MaxLen * sizeof(TCHAR));
249 if (SubKey == NULL)
250 {
251 wprintf(L"DS: HeapAlloc failed\n");
252 RegCloseKey(HandleKey);
253 return;
254 }
255
256 Index = 0;
257 Handled = 0;
258 Header = FALSE;
259 do
260 {
261 Ret = RegEnumKey(HandleKey, Index, SubKey, MaxLen);
262 if (Ret != ERROR_NO_MORE_ITEMS)
263 {
264 if (Image == NULL || wcscmp(SubKey, Image) == 0)
265 {
266 if (DisplayImageInfo(HandleKey, SubKey, &Header))
267 {
268 ++Handled;
269 }
270 }
271
272 ++Index;
273 }
274 } while (Ret != ERROR_NO_MORE_ITEMS);
275
276 if (Handled == 0)
277 {
278 if (Image == NULL)
279 {
280 wprintf(L"No application has page heap enabled.\n");
281 }
282 else
283 {
284 wprintf(L"Page heap is not enabled for %s\n", Image);
285 }
286 }
287
288 HeapFree(GetProcessHeap(), 0, SubKey);
289 RegCloseKey(HandleKey);
290 }
291
292 BOOL PageHeap_ParseCmdline(INT i, int argc, LPWSTR argv[])
293 {
294 for (; i < argc; i++)
295 {
296 if (argv[i][0] == L'/')
297 {
298 if (wcscmp(argv[i], L"/enable") == 0)
299 {
300 Set = TRUE;
301 }
302 else if (wcscmp(argv[i], L"/disable") == 0)
303 {
304 Unset = TRUE;
305 }
306 else if (wcscmp(argv[i], L"/full") == 0)
307 {
308 Full = TRUE;
309 }
310 }
311 else if (Image == NULL)
312 {
313 Image = argv[i];
314 }
315 else
316 {
317 wprintf(L"Invalid option: %s\n", argv[i]);
318 return FALSE;
319 }
320 }
321
322 if (Set && Unset)
323 {
324 wprintf(L"ENABLE and DISABLED cannot be set together\n");
325 return FALSE;
326 }
327
328 if (Image == NULL && (Set || Unset || Full))
329 {
330 wprintf(L"Can't ENABLE or DISABLE with no image\n");
331 return FALSE;
332 }
333
334 if (!Set && !Unset && Full)
335 {
336 wprintf(L"Cannot deal with full traces with no other indication\n");
337 return FALSE;
338 }
339
340 return TRUE;
341 }
342
343 INT PageHeap_Execute()
344 {
345 if (!Set && !Unset)
346 {
347 DisplayStatus();
348 }
349 else
350 {
351 ModifyStatus();
352 }
353
354 return 0;
355 }