https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8543622a720978599e435…
commit 8543622a720978599e4353810ec9c94a0ded36bd
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Sat Oct 13 17:11:51 2018 +0200
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Fri Oct 19 23:13:51 2018 +0200
[GFLAGS] Implement imagefile options
---
.../applications/cmdutils/gflags/CMakeLists.txt | 1 +
.../rosapps/applications/cmdutils/gflags/gflags.c | 28 ++-
.../rosapps/applications/cmdutils/gflags/gflags.h | 7 +
.../applications/cmdutils/gflags/imagefile.c | 263 +++++++++++++++++++++
4 files changed, 295 insertions(+), 4 deletions(-)
diff --git a/modules/rosapps/applications/cmdutils/gflags/CMakeLists.txt
b/modules/rosapps/applications/cmdutils/gflags/CMakeLists.txt
index fd935e76e8..e12052743f 100644
--- a/modules/rosapps/applications/cmdutils/gflags/CMakeLists.txt
+++ b/modules/rosapps/applications/cmdutils/gflags/CMakeLists.txt
@@ -2,6 +2,7 @@
list(APPEND SOURCE
gflags.c
+ imagefile.c
pageheap.c
gflags.h)
diff --git a/modules/rosapps/applications/cmdutils/gflags/gflags.c
b/modules/rosapps/applications/cmdutils/gflags/gflags.c
index ac2af7a8e9..f97f1f5f09 100644
--- a/modules/rosapps/applications/cmdutils/gflags/gflags.c
+++ b/modules/rosapps/applications/cmdutils/gflags/gflags.c
@@ -9,6 +9,7 @@
#include "gflags.h"
static BOOL UsePageHeap = FALSE;
+static BOOL UseImageFile = FALSE;
const WCHAR ImageExecOptionsString[] = L"Software\\Microsoft\\Windows
NT\\CurrentVersion\\Image File Execution Options";
@@ -77,6 +78,11 @@ static BOOL ParseCmdline(int argc, LPWSTR argv[])
UsePageHeap = TRUE;
return PageHeap_ParseCmdline(i + 1, argc, argv);
}
+ if (argv[i][1] == L'i' && argv[i][2] == UNICODE_NULL)
+ {
+ UseImageFile = TRUE;
+ return ImageFile_ParseCmdline(i + 1, argc, argv);
+ }
}
else
{
@@ -85,9 +91,9 @@ static BOOL ParseCmdline(int argc, LPWSTR argv[])
}
}
- if (!UsePageHeap)
+ if (!UsePageHeap && !UseImageFile)
{
- wprintf(L"Only page heap flags are supported\n");
+ wprintf(L"Only page heap / image file flags are supported\n");
return FALSE;
}
@@ -99,11 +105,21 @@ int wmain(int argc, LPWSTR argv[])
{
if (!ParseCmdline(argc, argv))
{
- wprintf(L"Usage: gflags /p [image.exe] [/enable|/disable [/full]]\n"
+ wprintf(L"Usage: gflags [/p [image.exe] [/enable|/disable [/full]]]\n"
+ L" [/i <image.exe> [<Flags>]]\n"
L" image.exe: Image you want to deal with\n"
L" /enable: enable page heap for the image\n"
L" /disable: disable page heap for the image\n"
- L" /full: activate full debug page heap\n");
+ L" /full: activate full debug page heap\n"
+ L" <Flags>: A 32 bit hex number (0x00000001) that
specifies\n"
+ L" one or more global flags to set.\n"
+ L" Without any flags, the current settings are
shown.\n"
+ L" Specify FFFFFFFF to delete the GlobalFlags
entry.\n"
+ L" Additionally, instead of a single hex
number,\n"
+ L" specify a list of abbreviations prefixed
with\n"
+ L" a '+' to add, and '-' to remove a
bit.\n"
+ L" Valid abbreviations:\n");
+ PrintFlags(~0, DEST_IMAGE);
return 1;
}
@@ -111,5 +127,9 @@ int wmain(int argc, LPWSTR argv[])
{
return PageHeap_Execute();
}
+ else if (UseImageFile)
+ {
+ return ImageFile_Execute();
+ }
return 2;
}
diff --git a/modules/rosapps/applications/cmdutils/gflags/gflags.h
b/modules/rosapps/applications/cmdutils/gflags/gflags.h
index 37674b67c7..d9c86a23f0 100644
--- a/modules/rosapps/applications/cmdutils/gflags/gflags.h
+++ b/modules/rosapps/applications/cmdutils/gflags/gflags.h
@@ -20,11 +20,18 @@ const WCHAR ImageExecOptionsString[];
/* Option specific commandline parsing */
BOOL PageHeap_ParseCmdline(INT i, int argc, LPWSTR argv[]);
+BOOL ImageFile_ParseCmdline(INT i, int argc, LPWSTR argv[]);
/* Execute parsed options */
INT PageHeap_Execute();
+INT ImageFile_Execute();
/* Common functions */
DWORD ReadSZFlagsFromRegistry(HKEY SubKey, PWSTR Value);
BOOL OpenImageFileExecOptions(IN REGSAM SamDesired, IN OPTIONAL PCWSTR ImageName, OUT
HKEY* Key);
+#define DEST_REGISTRY 1
+#define DEST_KERNEL 2
+#define DEST_IMAGE 4
+
+void PrintFlags(IN DWORD GlobalFlags, IN OPTIONAL WORD Dest);
diff --git a/modules/rosapps/applications/cmdutils/gflags/imagefile.c
b/modules/rosapps/applications/cmdutils/gflags/imagefile.c
new file mode 100644
index 0000000000..ba51c501d6
--- /dev/null
+++ b/modules/rosapps/applications/cmdutils/gflags/imagefile.c
@@ -0,0 +1,263 @@
+/*
+ * PROJECT: Global Flags utility
+ * LICENSE: GPL-2.0 (
https://spdx.org/licenses/GPL-2.0)
+ * PURPOSE: Global Flags utility image file options
+ * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen(a)reactos.org)
+ */
+
+#include "gflags.h"
+
+static PWSTR ImageFile = NULL;
+static DWORD OptionsAdd = 0;
+static DWORD OptionsRemove = 0;
+static BOOL OptionsSet = FALSE;
+
+typedef struct FlagInfo
+{
+ DWORD dwFlag;
+ const wchar_t* szAbbr;
+ WORD wDest;
+ const wchar_t* szDesc;
+} FlagInfo;
+
+#define FLG_DISABLE_DBGPRINT 0x8000000
+#define FLG_CRITSEC_EVENT_CREATION 0x10000000
+#define FLG_STOP_ON_UNHANDLED_EXCEPTION 0x20000000
+#define FLG_ENABLE_HANDLE_EXCEPTIONS 0x40000000
+#define FLG_DISABLE_PROTDLLS 0x80000000
+
+
+static const FlagInfo g_Flags[] =
+{
+ {FLG_STOP_ON_EXCEPTION, L"soe", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE),
L"Stop on exception"},
+ {FLG_SHOW_LDR_SNAPS, L"sls", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE),
L"Show loader snaps"},
+ {FLG_DEBUG_INITIAL_COMMAND, L"dic", (DEST_REGISTRY), L"Debug initial
command"},
+ {FLG_STOP_ON_HUNG_GUI, L"shg", (DEST_KERNEL), L"Stop on hung
GUI"},
+ {FLG_HEAP_ENABLE_TAIL_CHECK, L"htc", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Enable heap tail checking"},
+ {FLG_HEAP_ENABLE_FREE_CHECK, L"hfc", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Enable heap free checking"},
+ {FLG_HEAP_VALIDATE_PARAMETERS, L"hpc", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Enable heap parameter checking"},
+ {FLG_HEAP_VALIDATE_ALL, L"hvc", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE),
L"Enable heap validation on call"},
+ {FLG_APPLICATION_VERIFIER, L"vrf", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Enable application verifier"},
+ // FLG_MONITOR_SILENT_PROCESS_EXIT
+ {FLG_POOL_ENABLE_TAGGING, L"ptg", (DEST_REGISTRY), L"Enable pool
tagging"},
+ {FLG_HEAP_ENABLE_TAGGING, L"htg", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Enable heap tagging"},
+ {FLG_USER_STACK_TRACE_DB, L"ust", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Create user mode stack trace database"},
+ {FLG_KERNEL_STACK_TRACE_DB, L"kst", (DEST_REGISTRY), L"Create kernel
mode stack trace database"},
+ {FLG_MAINTAIN_OBJECT_TYPELIST, L"otl", (DEST_REGISTRY), L"Maintain a
list of objects for each type"},
+ {FLG_HEAP_ENABLE_TAG_BY_DLL, L"htd", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Enable heap tagging by DLL"},
+ {FLG_DISABLE_STACK_EXTENSION, L"dse", (DEST_IMAGE), L"Disable stack
extension"},
+
+ {FLG_ENABLE_CSRDEBUG, L"d32", (DEST_REGISTRY), L"Enable debugging of
Win32 subsystem"},
+ {FLG_ENABLE_KDEBUG_SYMBOL_LOAD, L"ksl", (DEST_REGISTRY | DEST_KERNEL),
L"Enable loading of kernel debugger symbols"},
+ {FLG_DISABLE_PAGE_KERNEL_STACKS, L"dps", (DEST_REGISTRY), L"Disable
paging of kernel stacks"},
+ {FLG_ENABLE_SYSTEM_CRIT_BREAKS, L"scb", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Enable system critical breaks"},
+ {FLG_HEAP_DISABLE_COALESCING, L"dhc", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Disable heap coalesce on free"},
+ {FLG_ENABLE_CLOSE_EXCEPTIONS, L"ece", (DEST_REGISTRY | DEST_KERNEL),
L"Enable close exception"},
+ {FLG_ENABLE_EXCEPTION_LOGGING, L"eel", (DEST_REGISTRY | DEST_KERNEL),
L"Enable exception logging"},
+ {FLG_ENABLE_HANDLE_TYPE_TAGGING, L"eot", (DEST_REGISTRY | DEST_KERNEL),
L"Enable object handle type tagging"},
+ {FLG_HEAP_PAGE_ALLOCS, L"hpa", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE),
L"Enable page heap"},
+ {FLG_DEBUG_INITIAL_COMMAND_EX, L"dwl", (DEST_REGISTRY), L"Debug
WinLogon"},
+ {FLG_DISABLE_DBGPRINT, L"ddp", (DEST_REGISTRY | DEST_KERNEL), L"Buffer
DbgPrint Output"},
+ {FLG_CRITSEC_EVENT_CREATION, L"cse", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Early critical section event creation"},
+ {FLG_STOP_ON_UNHANDLED_EXCEPTION, L"sue", (DEST_REGISTRY | DEST_KERNEL |
DEST_IMAGE), L"Stop on unhandled user-mode exception"},
+ {FLG_ENABLE_HANDLE_EXCEPTIONS, L"bhd", (DEST_REGISTRY | DEST_KERNEL),
L"Enable bad handles detection"},
+ {FLG_DISABLE_PROTDLLS, L"dpd", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE),
L"Disable protected DLL verification"},
+};
+
+void PrintFlags(IN DWORD GlobalFlags, IN OPTIONAL WORD Dest)
+{
+ DWORD n;
+
+ for (n = 0; n < ARRAYSIZE(g_Flags); ++n)
+ {
+ if (!Dest || (g_Flags[n].wDest & Dest))
+ {
+ if (g_Flags[n].dwFlag & GlobalFlags)
+ {
+ wprintf(L" %s - %s\n", g_Flags[n].szAbbr,
g_Flags[n].szDesc);
+ }
+ }
+ }
+}
+
+static void ShowStatus(DWORD GlobalFlags, DWORD Ignored)
+{
+ if (GlobalFlags)
+ {
+ wprintf(L"Current Registry Settings for %s executable are: %08x\n",
ImageFile, GlobalFlags);
+ PrintFlags(GlobalFlags, 0);
+ }
+ else
+ {
+ wprintf(L"No Registry Settings for %s executable\n", ImageFile);
+ }
+ if (Ignored)
+ {
+ wprintf(L"The following settings were ignored: %08x\n", Ignored);
+ PrintFlags(Ignored, 0);
+ }
+}
+
+static DWORD ValidateFlags(DWORD GlobalFlags, WORD Dest)
+{
+ DWORD n;
+ DWORD Valid = 0;
+
+ for (n = 0; n < ARRAYSIZE(g_Flags); ++n)
+ {
+ if (g_Flags[n].wDest & Dest)
+ {
+ Valid |= g_Flags[n].dwFlag;
+ }
+ }
+
+ return GlobalFlags & Valid;
+}
+
+static DWORD FindFlag(PCWSTR Name, WORD Dest)
+{
+ DWORD n;
+
+ for (n = 0; n < ARRAYSIZE(g_Flags); ++n)
+ {
+ if (g_Flags[n].wDest & Dest)
+ {
+ if (!wcsicmp(Name, g_Flags[n].szAbbr))
+ {
+ return g_Flags[n].dwFlag;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static VOID ModifyStatus(VOID)
+{
+ LONG Ret;
+ DWORD GlobalFlags, Requested, Ignored;
+ HKEY IFEOKey;
+ WCHAR Buffer[11];
+
+ if (!OpenImageFileExecOptions(KEY_WRITE | KEY_READ, ImageFile, &IFEOKey))
+ {
+ return;
+ }
+
+ if (OptionsSet)
+ {
+ Requested = OptionsAdd;
+ }
+ else
+ {
+ Requested = ReadSZFlagsFromRegistry(IFEOKey, L"GlobalFlag");
+ Requested &= ~OptionsRemove;
+ Requested |= OptionsAdd;
+ }
+
+ GlobalFlags = ValidateFlags(Requested, DEST_IMAGE);
+ Ignored = GlobalFlags ^ Requested;
+
+ if (GlobalFlags)
+ {
+ wsprintf(Buffer, L"0x%08x", GlobalFlags);
+ Ret = RegSetValueExW(IFEOKey, L"GlobalFlag", 0, REG_SZ, (BYTE*)Buffer,
(wcslen(Buffer) + 1) * sizeof(WCHAR));
+ if (Ret != ERROR_SUCCESS)
+ {
+ wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret);
+ }
+ else
+ {
+ ShowStatus(GlobalFlags, Ignored);
+ }
+ }
+ else
+ {
+ Ret = RegDeleteValueW(IFEOKey, L"GlobalFlag");
+ if (Ret != ERROR_SUCCESS)
+ {
+ wprintf(L"MS: RegDeleteValue failed (%d)\n", Ret);
+ }
+ else
+ {
+ ShowStatus(GlobalFlags, Ignored);
+ }
+ }
+ CloseHandle(IFEOKey);
+}
+
+
+static VOID DisplayStatus(VOID)
+{
+ HKEY IFEOKey;
+ DWORD GlobalFlags;
+
+ if (!OpenImageFileExecOptions(KEY_READ, ImageFile, &IFEOKey))
+ {
+ return;
+ }
+
+ GlobalFlags = ReadSZFlagsFromRegistry(IFEOKey, L"GlobalFlag");
+ ShowStatus(GlobalFlags, 0);
+
+ CloseHandle(IFEOKey);
+}
+
+
+BOOL ImageFile_ParseCmdline(INT i, int argc, LPWSTR argv[])
+{
+ for (; i < argc; i++)
+ {
+ if (ImageFile == NULL)
+ {
+ ImageFile = argv[i];
+ }
+ else if (argv[i][0] == '+')
+ {
+ if (OptionsSet)
+ {
+ wprintf(L"Unexpected argument - '%s'\n", argv[i]);
+ return FALSE;
+ }
+ OptionsAdd |= FindFlag(argv[i] + 1, DEST_IMAGE);
+ }
+ else if (argv[i][0] == '-')
+ {
+ if (OptionsSet)
+ {
+ wprintf(L"Unexpected argument - '%s'\n", argv[i]);
+ return FALSE;
+ }
+ OptionsRemove |= FindFlag(argv[i] + 1, DEST_IMAGE);
+ }
+ else
+ {
+ OptionsSet = TRUE;
+ OptionsAdd = wcstoul(argv[i], NULL, 16);
+ if (OptionsAdd == ~0)
+ OptionsAdd = 0;
+ }
+ }
+
+ if (ImageFile == NULL)
+ {
+ wprintf(L"No Image specified\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+INT ImageFile_Execute()
+{
+ if (!OptionsAdd && !OptionsRemove && !OptionsSet)
+ {
+ DisplayStatus();
+ }
+ else
+ {
+ ModifyStatus();
+ }
+
+ return 0;
+}