mirror of
https://github.com/reactos/reactos.git
synced 2025-05-07 02:41:22 +00:00
[GFLAGS] Move code around to handle multiple options
This commit is contained in:
parent
05c2e3e89e
commit
bc3b356ae6
4 changed files with 409 additions and 363 deletions
|
@ -1,7 +1,14 @@
|
||||||
|
|
||||||
add_executable(gflags gflags.c gflags.rc)
|
|
||||||
|
list(APPEND SOURCE
|
||||||
|
gflags.c
|
||||||
|
pageheap.c
|
||||||
|
gflags.h)
|
||||||
|
|
||||||
|
add_executable(gflags ${SOURCE} gflags.rc)
|
||||||
set_module_type(gflags win32cui UNICODE)
|
set_module_type(gflags win32cui UNICODE)
|
||||||
add_importlibs(gflags advapi32 user32 msvcrt kernel32)
|
add_importlibs(gflags advapi32 user32 msvcrt kernel32)
|
||||||
|
add_pch(gflags gflags.h SOURCE)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_importlibs(gflags ntdll)
|
add_importlibs(gflags ntdll)
|
||||||
|
|
|
@ -1,27 +1,17 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* PROJECT: Global Flags utility
|
||||||
* PROJECT: ReactOS ping utility
|
* LICENSE: GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
|
||||||
* FILE: applications/cmdutils/gflags/gflags.c
|
* PURPOSE: Global Flags utility entrypoint
|
||||||
* PURPOSE: Global Flags utility
|
* COPYRIGHT: Copyright 2017 Pierre Schweitzer (pierre@reactos.org)
|
||||||
* PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
|
* Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define WIN32_NO_STATUS
|
#include "gflags.h"
|
||||||
#include <stdarg.h>
|
|
||||||
#include <windef.h>
|
|
||||||
#include <winbase.h>
|
|
||||||
#include <winuser.h>
|
|
||||||
#include <winreg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
static BOOL Set = FALSE;
|
static BOOL UsePageHeap = FALSE;
|
||||||
static BOOL Unset = FALSE;
|
|
||||||
static BOOL Full = FALSE;
|
|
||||||
static PWSTR Image = NULL;
|
|
||||||
static WCHAR ImageExecOptionsString[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options";
|
|
||||||
|
|
||||||
static DWORD ReagFlagsFromRegistry(HKEY SubKey, PVOID Buffer, PWSTR Value, DWORD MaxLen)
|
|
||||||
|
DWORD ReagFlagsFromRegistry(HKEY SubKey, PVOID Buffer, PWSTR Value, DWORD MaxLen)
|
||||||
{
|
{
|
||||||
DWORD Len, Flags, Type;
|
DWORD Len, Flags, Type;
|
||||||
|
|
||||||
|
@ -35,299 +25,13 @@ static DWORD ReagFlagsFromRegistry(HKEY SubKey, PVOID Buffer, PWSTR Value, DWORD
|
||||||
return Flags;
|
return Flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID ModifyStatus(VOID)
|
|
||||||
{
|
|
||||||
LONG Ret;
|
|
||||||
DWORD MaxLen, GlobalFlags;
|
|
||||||
PVOID Buffer;
|
|
||||||
HKEY HandleKey, HandleSubKey;
|
|
||||||
|
|
||||||
Ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ImageExecOptionsString, 0, KEY_WRITE | KEY_READ, &HandleKey);
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"MS: RegOpenKeyEx failed (%d)\n", Ret);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ret = RegCreateKeyEx(HandleKey, Image, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &HandleSubKey, NULL);
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"MS: RegCreateKeyEx failed (%d)\n", Ret);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ret = RegQueryInfoKey(HandleSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL);
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"MS: RegQueryInfoKey failed (%d)\n", Ret);
|
|
||||||
RegCloseKey(HandleSubKey);
|
|
||||||
RegCloseKey(HandleKey);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaxLen = max(MaxLen, 11 * sizeof(WCHAR));
|
|
||||||
Buffer = HeapAlloc(GetProcessHeap(), 0, MaxLen);
|
|
||||||
if (Buffer == NULL)
|
|
||||||
{
|
|
||||||
wprintf(L"MS: HeapAlloc failed\n");
|
|
||||||
RegCloseKey(HandleSubKey);
|
|
||||||
RegCloseKey(HandleKey);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"GlobalFlag", MaxLen);
|
|
||||||
if (Set)
|
|
||||||
{
|
|
||||||
GlobalFlags |= 0x02000000;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GlobalFlags &= ~0x02000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GlobalFlags != 0)
|
|
||||||
{
|
|
||||||
wsprintf(Buffer, L"0x%08x", GlobalFlags);
|
|
||||||
Ret = RegSetValueEx(HandleSubKey, L"GlobalFlag", 0, REG_SZ, Buffer, 11 * sizeof(WCHAR));
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Ret = RegDeleteValue(HandleSubKey, L"GlobalFlag");
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"MS: RegDeleteValue failed (%d)\n", Ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Unset)
|
|
||||||
{
|
|
||||||
Ret = RegDeleteValue(HandleSubKey, L"PageHeapFlags");
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"MS: RegDeleteValue failed (%d)\n", Ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DWORD PageHeapFlags;
|
|
||||||
|
|
||||||
PageHeapFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"PageHeapFlags", MaxLen);
|
|
||||||
PageHeapFlags &= ~3;
|
|
||||||
|
|
||||||
if (Full)
|
|
||||||
{
|
|
||||||
PageHeapFlags |= 1;
|
|
||||||
}
|
|
||||||
PageHeapFlags |= 2;
|
|
||||||
|
|
||||||
wsprintf(Buffer, L"0x%x", PageHeapFlags);
|
|
||||||
Ret = RegSetValueEx(HandleSubKey, L"PageHeapFlags", 0, REG_SZ, Buffer, 11 * sizeof(WCHAR));
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Set)
|
|
||||||
{
|
|
||||||
DWORD Type, VerifierFlags, Len;
|
|
||||||
|
|
||||||
VerifierFlags = 0;
|
|
||||||
Len = MaxLen;
|
|
||||||
if (RegQueryValueEx(HandleSubKey, L"VerifierFlags", NULL, &Type, Buffer, &Len) == ERROR_SUCCESS &&
|
|
||||||
Type == REG_DWORD && Len == sizeof(DWORD))
|
|
||||||
{
|
|
||||||
VerifierFlags = ((DWORD *)Buffer)[0];
|
|
||||||
VerifierFlags &= ~0x8001;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Full)
|
|
||||||
{
|
|
||||||
VerifierFlags |= 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VerifierFlags |= 0x8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ret = RegSetValueEx(HandleSubKey, L"VerifierFlags", 0, REG_DWORD, (const BYTE *)&VerifierFlags, sizeof(DWORD));
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wprintf(L"path: %s\n", ImageExecOptionsString);
|
|
||||||
wprintf(L"\t%s: page heap %s\n", Image, (Set ? L"enabled" : L"disabled"));
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, Buffer);
|
|
||||||
RegCloseKey(HandleSubKey);
|
|
||||||
RegCloseKey(HandleKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL DisplayImageInfo(HKEY HandleKey, PWSTR SubKey, PBOOL Header)
|
|
||||||
{
|
|
||||||
LONG Ret;
|
|
||||||
BOOL Handled;
|
|
||||||
DWORD MaxLen, GlobalFlags;
|
|
||||||
HKEY HandleSubKey;
|
|
||||||
PVOID Buffer;
|
|
||||||
|
|
||||||
Ret = RegOpenKeyEx(HandleKey, SubKey, 0, KEY_READ, &HandleSubKey);
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"DII: RegOpenKeyEx failed (%d)\n", Ret);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ret = RegQueryInfoKey(HandleSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL);
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"DII: RegQueryInfoKey failed (%d)\n", Ret);
|
|
||||||
RegCloseKey(HandleSubKey);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Buffer = HeapAlloc(GetProcessHeap(), 0, MaxLen);
|
|
||||||
if (Buffer == NULL)
|
|
||||||
{
|
|
||||||
wprintf(L"DII: HeapAlloc failed\n");
|
|
||||||
RegCloseKey(HandleSubKey);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Handled = FALSE;
|
|
||||||
GlobalFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"GlobalFlag", MaxLen);
|
|
||||||
if (GlobalFlags & 0x02000000)
|
|
||||||
{
|
|
||||||
DWORD PageHeapFlags;
|
|
||||||
|
|
||||||
if (Image == NULL)
|
|
||||||
{
|
|
||||||
if (!*Header)
|
|
||||||
{
|
|
||||||
wprintf(L"path: %s\n", ImageExecOptionsString);
|
|
||||||
*Header = TRUE;
|
|
||||||
}
|
|
||||||
wprintf(L"\t%s: page heap enabled with flags (", SubKey);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wprintf(L"Page heap is enabled for %s with flags (", SubKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
PageHeapFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"PageHeapFlags", MaxLen);
|
|
||||||
if (PageHeapFlags & 0x1)
|
|
||||||
{
|
|
||||||
wprintf(L"full ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PageHeapFlags & 0x2)
|
|
||||||
{
|
|
||||||
wprintf(L"traces");
|
|
||||||
}
|
|
||||||
|
|
||||||
wprintf(L")\n");
|
|
||||||
|
|
||||||
Handled = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, Buffer);
|
|
||||||
RegCloseKey(HandleSubKey);
|
|
||||||
|
|
||||||
return Handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID DisplayStatus(VOID)
|
|
||||||
{
|
|
||||||
LONG Ret;
|
|
||||||
HKEY HandleKey;
|
|
||||||
DWORD Index, MaxLen, Handled;
|
|
||||||
TCHAR * SubKey;
|
|
||||||
BOOL Header;
|
|
||||||
|
|
||||||
Ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ImageExecOptionsString, 0, KEY_READ, &HandleKey);
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"DS: RegOpenKeyEx failed (%d)\n", Ret);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ret = RegQueryInfoKey(HandleKey, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
wprintf(L"DS: RegQueryInfoKey failed (%d)\n", Ret);
|
|
||||||
RegCloseKey(HandleKey);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
++MaxLen; // NULL-char
|
|
||||||
SubKey = HeapAlloc(GetProcessHeap(), 0, MaxLen * sizeof(TCHAR));
|
|
||||||
if (SubKey == NULL)
|
|
||||||
{
|
|
||||||
wprintf(L"DS: HeapAlloc failed\n");
|
|
||||||
RegCloseKey(HandleKey);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Index = 0;
|
|
||||||
Handled = 0;
|
|
||||||
Header = FALSE;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Ret = RegEnumKey(HandleKey, Index, SubKey, MaxLen);
|
|
||||||
if (Ret != ERROR_NO_MORE_ITEMS)
|
|
||||||
{
|
|
||||||
if (Image == NULL || wcscmp(SubKey, Image) == 0)
|
|
||||||
{
|
|
||||||
if (DisplayImageInfo(HandleKey, SubKey, &Header))
|
|
||||||
{
|
|
||||||
++Handled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++Index;
|
|
||||||
}
|
|
||||||
} while (Ret != ERROR_NO_MORE_ITEMS);
|
|
||||||
|
|
||||||
if (Handled == 0)
|
|
||||||
{
|
|
||||||
if (Image == NULL)
|
|
||||||
{
|
|
||||||
wprintf(L"No application has page heap enabled.\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wprintf(L"Page heap is not enabled for %s\n", Image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, SubKey);
|
|
||||||
RegCloseKey(HandleKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID Usage(VOID)
|
|
||||||
{
|
|
||||||
wprintf(L"Usage: gflags /p [image.exe] [/enable|/disable [/full]]\n"
|
|
||||||
L"\timage.exe:\tImage you want to deal with\n"
|
|
||||||
L"\t/enable:\tenable page heap for the image\n"
|
|
||||||
L"\t/disable:\tdisable page heap for the image\n"
|
|
||||||
L"\t/full:\t\tactivate full debug page heap\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL ParseCmdline(int argc, LPWSTR argv[])
|
static BOOL ParseCmdline(int argc, LPWSTR argv[])
|
||||||
{
|
{
|
||||||
INT i;
|
INT i;
|
||||||
BOOL UsePageHeap = FALSE;
|
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
wprintf(L"Not enough args!\n", argc);
|
wprintf(L"Not enough args!\n");
|
||||||
Usage();
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,37 +42,12 @@ static BOOL ParseCmdline(int argc, LPWSTR argv[])
|
||||||
if (argv[i][1] == L'p' && argv[i][2] == UNICODE_NULL)
|
if (argv[i][1] == L'p' && argv[i][2] == UNICODE_NULL)
|
||||||
{
|
{
|
||||||
UsePageHeap = TRUE;
|
UsePageHeap = TRUE;
|
||||||
|
return PageHeap_ParseCmdline(i + 1, argc, argv);
|
||||||
}
|
}
|
||||||
else if (argv[i][1] == L'p' && argv[i][2] != UNICODE_NULL)
|
|
||||||
{
|
|
||||||
wprintf(L"Invalid option: %s\n", argv[i]);
|
|
||||||
Usage();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (wcscmp(argv[i], L"/enable") == 0)
|
|
||||||
{
|
|
||||||
Set = TRUE;
|
|
||||||
}
|
|
||||||
else if (wcscmp(argv[i], L"/disable") == 0)
|
|
||||||
{
|
|
||||||
Unset = TRUE;
|
|
||||||
}
|
|
||||||
else if (wcscmp(argv[i], L"/full") == 0)
|
|
||||||
{
|
|
||||||
Full = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Image == NULL)
|
|
||||||
{
|
|
||||||
Image = argv[i];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wprintf(L"Invalid option: %s\n", argv[i]);
|
wprintf(L"Invalid option: %s\n", argv[i]);
|
||||||
Usage();
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,49 +55,28 @@ static BOOL ParseCmdline(int argc, LPWSTR argv[])
|
||||||
if (!UsePageHeap)
|
if (!UsePageHeap)
|
||||||
{
|
{
|
||||||
wprintf(L"Only page heap flags are supported\n");
|
wprintf(L"Only page heap flags are supported\n");
|
||||||
Usage();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Set && Unset)
|
|
||||||
{
|
|
||||||
wprintf(L"ENABLE and DISABLED cannot be set together\n");
|
|
||||||
Usage();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Image == NULL && (Set || Unset || Full))
|
|
||||||
{
|
|
||||||
wprintf(L"Can't ENABLE or DISABLE with no image\n");
|
|
||||||
Usage();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Set && !Unset && Full)
|
|
||||||
{
|
|
||||||
wprintf(L"Cannot deal with full traces with no other indication\n");
|
|
||||||
Usage();
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wmain(int argc, LPWSTR argv[])
|
int wmain(int argc, LPWSTR argv[])
|
||||||
{
|
{
|
||||||
if (!ParseCmdline(argc, argv))
|
if (!ParseCmdline(argc, argv))
|
||||||
{
|
{
|
||||||
|
wprintf(L"Usage: gflags /p [image.exe] [/enable|/disable [/full]]\n"
|
||||||
|
L"\timage.exe:\tImage you want to deal with\n"
|
||||||
|
L"\t/enable:\tenable page heap for the image\n"
|
||||||
|
L"\t/disable:\tdisable page heap for the image\n"
|
||||||
|
L"\t/full:\t\tactivate full debug page heap\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Set && !Unset)
|
if (UsePageHeap)
|
||||||
{
|
{
|
||||||
DisplayStatus();
|
return PageHeap_Execute();
|
||||||
}
|
}
|
||||||
else
|
return 2;
|
||||||
{
|
|
||||||
ModifyStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
26
modules/rosapps/applications/cmdutils/gflags/gflags.h
Normal file
26
modules/rosapps/applications/cmdutils/gflags/gflags.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: Global Flags utility
|
||||||
|
* LICENSE: GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
|
||||||
|
* PURPOSE: Global Flags utility page heap options
|
||||||
|
* COPYRIGHT: Copyright 2017 Pierre Schweitzer (pierre@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <windef.h>
|
||||||
|
#include <winbase.h>
|
||||||
|
#include <winuser.h>
|
||||||
|
#include <winreg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Option specific commandline parsing */
|
||||||
|
BOOL PageHeap_ParseCmdline(INT i, int argc, LPWSTR argv[]);
|
||||||
|
|
||||||
|
/* Execute parsed options */
|
||||||
|
INT PageHeap_Execute();
|
||||||
|
|
||||||
|
/* Common functions */
|
||||||
|
DWORD ReagFlagsFromRegistry(HKEY SubKey, PVOID Buffer, PWSTR Value, DWORD MaxLen);
|
||||||
|
|
355
modules/rosapps/applications/cmdutils/gflags/pageheap.c
Normal file
355
modules/rosapps/applications/cmdutils/gflags/pageheap.c
Normal file
|
@ -0,0 +1,355 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: Global Flags utility
|
||||||
|
* LICENSE: GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
|
||||||
|
* PURPOSE: Global Flags utility page heap options
|
||||||
|
* COPYRIGHT: Copyright 2017 Pierre Schweitzer (pierre@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gflags.h"
|
||||||
|
|
||||||
|
static BOOL Set = FALSE;
|
||||||
|
static BOOL Unset = FALSE;
|
||||||
|
static BOOL Full = FALSE;
|
||||||
|
static PWSTR Image = NULL;
|
||||||
|
static WCHAR ImageExecOptionsString[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options";
|
||||||
|
|
||||||
|
|
||||||
|
static VOID ModifyStatus(VOID)
|
||||||
|
{
|
||||||
|
LONG Ret;
|
||||||
|
DWORD MaxLen, GlobalFlags;
|
||||||
|
PVOID Buffer;
|
||||||
|
HKEY HandleKey, HandleSubKey;
|
||||||
|
|
||||||
|
Ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ImageExecOptionsString, 0, KEY_WRITE | KEY_READ, &HandleKey);
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"MS: RegOpenKeyEx failed (%d)\n", Ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ret = RegCreateKeyEx(HandleKey, Image, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &HandleSubKey, NULL);
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"MS: RegCreateKeyEx failed (%d)\n", Ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ret = RegQueryInfoKey(HandleSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL);
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"MS: RegQueryInfoKey failed (%d)\n", Ret);
|
||||||
|
RegCloseKey(HandleSubKey);
|
||||||
|
RegCloseKey(HandleKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaxLen = max(MaxLen, 11 * sizeof(WCHAR));
|
||||||
|
Buffer = HeapAlloc(GetProcessHeap(), 0, MaxLen);
|
||||||
|
if (Buffer == NULL)
|
||||||
|
{
|
||||||
|
wprintf(L"MS: HeapAlloc failed\n");
|
||||||
|
RegCloseKey(HandleSubKey);
|
||||||
|
RegCloseKey(HandleKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"GlobalFlag", MaxLen);
|
||||||
|
if (Set)
|
||||||
|
{
|
||||||
|
GlobalFlags |= 0x02000000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GlobalFlags &= ~0x02000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GlobalFlags != 0)
|
||||||
|
{
|
||||||
|
wsprintf(Buffer, L"0x%08x", GlobalFlags);
|
||||||
|
Ret = RegSetValueEx(HandleSubKey, L"GlobalFlag", 0, REG_SZ, Buffer, 11 * sizeof(WCHAR));
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Ret = RegDeleteValue(HandleSubKey, L"GlobalFlag");
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"MS: RegDeleteValue failed (%d)\n", Ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Unset)
|
||||||
|
{
|
||||||
|
Ret = RegDeleteValue(HandleSubKey, L"PageHeapFlags");
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"MS: RegDeleteValue failed (%d)\n", Ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DWORD PageHeapFlags;
|
||||||
|
|
||||||
|
PageHeapFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"PageHeapFlags", MaxLen);
|
||||||
|
PageHeapFlags &= ~3;
|
||||||
|
|
||||||
|
if (Full)
|
||||||
|
{
|
||||||
|
PageHeapFlags |= 1;
|
||||||
|
}
|
||||||
|
PageHeapFlags |= 2;
|
||||||
|
|
||||||
|
wsprintf(Buffer, L"0x%x", PageHeapFlags);
|
||||||
|
Ret = RegSetValueEx(HandleSubKey, L"PageHeapFlags", 0, REG_SZ, Buffer, 11 * sizeof(WCHAR));
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Set)
|
||||||
|
{
|
||||||
|
DWORD Type, VerifierFlags, Len;
|
||||||
|
|
||||||
|
VerifierFlags = 0;
|
||||||
|
Len = MaxLen;
|
||||||
|
if (RegQueryValueEx(HandleSubKey, L"VerifierFlags", NULL, &Type, Buffer, &Len) == ERROR_SUCCESS &&
|
||||||
|
Type == REG_DWORD && Len == sizeof(DWORD))
|
||||||
|
{
|
||||||
|
VerifierFlags = ((DWORD *)Buffer)[0];
|
||||||
|
VerifierFlags &= ~0x8001;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Full)
|
||||||
|
{
|
||||||
|
VerifierFlags |= 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VerifierFlags |= 0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ret = RegSetValueEx(HandleSubKey, L"VerifierFlags", 0, REG_DWORD, (const BYTE *)&VerifierFlags, sizeof(DWORD));
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wprintf(L"path: %s\n", ImageExecOptionsString);
|
||||||
|
wprintf(L"\t%s: page heap %s\n", Image, (Set ? L"enabled" : L"disabled"));
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, Buffer);
|
||||||
|
RegCloseKey(HandleSubKey);
|
||||||
|
RegCloseKey(HandleKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL DisplayImageInfo(HKEY HandleKey, PWSTR SubKey, PBOOL Header)
|
||||||
|
{
|
||||||
|
LONG Ret;
|
||||||
|
BOOL Handled;
|
||||||
|
DWORD MaxLen, GlobalFlags;
|
||||||
|
HKEY HandleSubKey;
|
||||||
|
PVOID Buffer;
|
||||||
|
|
||||||
|
Ret = RegOpenKeyEx(HandleKey, SubKey, 0, KEY_READ, &HandleSubKey);
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"DII: RegOpenKeyEx failed (%d)\n", Ret);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ret = RegQueryInfoKey(HandleSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL);
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"DII: RegQueryInfoKey failed (%d)\n", Ret);
|
||||||
|
RegCloseKey(HandleSubKey);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer = HeapAlloc(GetProcessHeap(), 0, MaxLen);
|
||||||
|
if (Buffer == NULL)
|
||||||
|
{
|
||||||
|
wprintf(L"DII: HeapAlloc failed\n");
|
||||||
|
RegCloseKey(HandleSubKey);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handled = FALSE;
|
||||||
|
GlobalFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"GlobalFlag", MaxLen);
|
||||||
|
if (GlobalFlags & 0x02000000)
|
||||||
|
{
|
||||||
|
DWORD PageHeapFlags;
|
||||||
|
|
||||||
|
if (Image == NULL)
|
||||||
|
{
|
||||||
|
if (!*Header)
|
||||||
|
{
|
||||||
|
wprintf(L"path: %s\n", ImageExecOptionsString);
|
||||||
|
*Header = TRUE;
|
||||||
|
}
|
||||||
|
wprintf(L"\t%s: page heap enabled with flags (", SubKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wprintf(L"Page heap is enabled for %s with flags (", SubKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
PageHeapFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"PageHeapFlags", MaxLen);
|
||||||
|
if (PageHeapFlags & 0x1)
|
||||||
|
{
|
||||||
|
wprintf(L"full ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PageHeapFlags & 0x2)
|
||||||
|
{
|
||||||
|
wprintf(L"traces");
|
||||||
|
}
|
||||||
|
|
||||||
|
wprintf(L")\n");
|
||||||
|
|
||||||
|
Handled = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, Buffer);
|
||||||
|
RegCloseKey(HandleSubKey);
|
||||||
|
|
||||||
|
return Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID DisplayStatus(VOID)
|
||||||
|
{
|
||||||
|
LONG Ret;
|
||||||
|
HKEY HandleKey;
|
||||||
|
DWORD Index, MaxLen, Handled;
|
||||||
|
TCHAR * SubKey;
|
||||||
|
BOOL Header;
|
||||||
|
|
||||||
|
Ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ImageExecOptionsString, 0, KEY_READ, &HandleKey);
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"DS: RegOpenKeyEx failed (%d)\n", Ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ret = RegQueryInfoKey(HandleKey, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
wprintf(L"DS: RegQueryInfoKey failed (%d)\n", Ret);
|
||||||
|
RegCloseKey(HandleKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++MaxLen; // NULL-char
|
||||||
|
SubKey = HeapAlloc(GetProcessHeap(), 0, MaxLen * sizeof(TCHAR));
|
||||||
|
if (SubKey == NULL)
|
||||||
|
{
|
||||||
|
wprintf(L"DS: HeapAlloc failed\n");
|
||||||
|
RegCloseKey(HandleKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index = 0;
|
||||||
|
Handled = 0;
|
||||||
|
Header = FALSE;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Ret = RegEnumKey(HandleKey, Index, SubKey, MaxLen);
|
||||||
|
if (Ret != ERROR_NO_MORE_ITEMS)
|
||||||
|
{
|
||||||
|
if (Image == NULL || wcscmp(SubKey, Image) == 0)
|
||||||
|
{
|
||||||
|
if (DisplayImageInfo(HandleKey, SubKey, &Header))
|
||||||
|
{
|
||||||
|
++Handled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++Index;
|
||||||
|
}
|
||||||
|
} while (Ret != ERROR_NO_MORE_ITEMS);
|
||||||
|
|
||||||
|
if (Handled == 0)
|
||||||
|
{
|
||||||
|
if (Image == NULL)
|
||||||
|
{
|
||||||
|
wprintf(L"No application has page heap enabled.\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wprintf(L"Page heap is not enabled for %s\n", Image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, SubKey);
|
||||||
|
RegCloseKey(HandleKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL PageHeap_ParseCmdline(INT i, int argc, LPWSTR argv[])
|
||||||
|
{
|
||||||
|
for (; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (argv[i][0] == L'/')
|
||||||
|
{
|
||||||
|
if (wcscmp(argv[i], L"/enable") == 0)
|
||||||
|
{
|
||||||
|
Set = TRUE;
|
||||||
|
}
|
||||||
|
else if (wcscmp(argv[i], L"/disable") == 0)
|
||||||
|
{
|
||||||
|
Unset = TRUE;
|
||||||
|
}
|
||||||
|
else if (wcscmp(argv[i], L"/full") == 0)
|
||||||
|
{
|
||||||
|
Full = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Image == NULL)
|
||||||
|
{
|
||||||
|
Image = argv[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wprintf(L"Invalid option: %s\n", argv[i]);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Set && Unset)
|
||||||
|
{
|
||||||
|
wprintf(L"ENABLE and DISABLED cannot be set together\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Image == NULL && (Set || Unset || Full))
|
||||||
|
{
|
||||||
|
wprintf(L"Can't ENABLE or DISABLE with no image\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Set && !Unset && Full)
|
||||||
|
{
|
||||||
|
wprintf(L"Cannot deal with full traces with no other indication\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
INT PageHeap_Execute()
|
||||||
|
{
|
||||||
|
if (!Set && !Unset)
|
||||||
|
{
|
||||||
|
DisplayStatus();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ModifyStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue