From: Mark Jansen Date: Sat, 13 Oct 2018 15:11:51 +0000 (+0200) Subject: [GFLAGS] Implement imagefile options X-Git-Tag: 0.4.12-dev~508 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=8543622a720978599e4353810ec9c94a0ded36bd [GFLAGS] Implement imagefile options --- diff --git a/modules/rosapps/applications/cmdutils/gflags/CMakeLists.txt b/modules/rosapps/applications/cmdutils/gflags/CMakeLists.txt index fd935e76e82..e12052743f0 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 ac2af7a8e95..f97f1f5f098 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 []]\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" : 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 37674b67c79..d9c86a23f07 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 00000000000..ba51c501d6e --- /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@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; +}