mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[GFLAGS] Implement imagefile options
This commit is contained in:
parent
ec621270a1
commit
8543622a72
4 changed files with 295 additions and 4 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||
list(APPEND SOURCE
|
||||
gflags.c
|
||||
imagefile.c
|
||||
pageheap.c
|
||||
gflags.h)
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
263
modules/rosapps/applications/cmdutils/gflags/imagefile.c
Normal file
263
modules/rosapps/applications/cmdutils/gflags/imagefile.c
Normal file
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue